Commit 0c0a2adc authored by Henri Verbeet's avatar Henri Verbeet Committed by Alexandre Julliard

wined3d: Handle GL texture allocation in the texture code.

parent 77646173
......@@ -141,7 +141,7 @@ static void context_attach_depth_stencil_fbo(struct wined3d_context *context,
{
case WINED3D_LOCATION_TEXTURE_RGB:
case WINED3D_LOCATION_TEXTURE_SRGB:
surface_prepare_texture(depth_stencil, context, FALSE);
wined3d_texture_prepare_texture(depth_stencil->container, context, FALSE);
if (format_flags & WINED3DFMT_FLAG_DEPTH)
{
......@@ -217,7 +217,7 @@ static void context_attach_surface_fbo(struct wined3d_context *context,
case WINED3D_LOCATION_TEXTURE_RGB:
case WINED3D_LOCATION_TEXTURE_SRGB:
srgb = location == WINED3D_LOCATION_TEXTURE_SRGB;
surface_prepare_texture(surface, context, srgb);
wined3d_texture_prepare_texture(surface->container, context, srgb);
gl_info->fbo_ops.glFramebufferTexture2D(fbo_target, GL_COLOR_ATTACHMENT0 + idx,
surface->texture_target, surface_get_texture_name(surface, gl_info, srgb),
surface->texture_level);
......
......@@ -1697,7 +1697,7 @@ HRESULT surface_upload_from_surface(struct wined3d_surface *dst_surface, const P
* the texture wouldn't be the current location, and we'd upload zeroes
* just to overwrite them again. */
if (update_w == dst_w && update_h == dst_h)
surface_prepare_texture(dst_surface, context, FALSE);
wined3d_texture_prepare_texture(dst_surface->container, context, FALSE);
else
surface_load_location(dst_surface, WINED3D_LOCATION_TEXTURE_RGB);
wined3d_texture_bind(dst_surface->container, context, FALSE);
......@@ -1717,83 +1717,6 @@ HRESULT surface_upload_from_surface(struct wined3d_surface *dst_surface, const P
return WINED3D_OK;
}
/* This call just allocates the texture, the caller is responsible for binding
* the correct texture. */
/* Context activation is done by the caller. */
static void surface_allocate_surface(struct wined3d_surface *surface, const struct wined3d_gl_info *gl_info,
const struct wined3d_format *format, BOOL srgb)
{
BOOL disable_client_storage = FALSE;
GLsizei width = surface->pow2Width;
GLsizei height = surface->pow2Height;
const BYTE *mem = NULL;
GLenum internal;
if (srgb)
internal = format->glGammaInternal;
else if (surface->resource.usage & WINED3DUSAGE_RENDERTARGET
&& wined3d_resource_is_offscreen(&surface->container->resource))
internal = format->rtInternal;
else
internal = format->glInternal;
if (!internal)
FIXME("No GL internal format for format %s.\n", debug_d3dformat(format->id));
if (format->flags & WINED3DFMT_FLAG_HEIGHT_SCALE)
{
height *= format->height_scale.numerator;
height /= format->height_scale.denominator;
}
TRACE("(%p) : Creating surface (target %#x) level %d, d3d format %s, internal format %#x, width %d, height %d, gl format %#x, gl type=%#x\n",
surface, surface->texture_target, surface->texture_level, debug_d3dformat(format->id),
internal, width, height, format->glFormat, format->glType);
if (gl_info->supported[APPLE_CLIENT_STORAGE])
{
if (surface->flags & (SFLAG_NONPOW2 | SFLAG_DIBSECTION | SFLAG_CONVERTED)
|| !surface->resource.heap_memory)
{
/* In some cases we want to disable client storage.
* SFLAG_NONPOW2 has a bigger opengl texture than the client memory, and different pitches
* SFLAG_DIBSECTION: Dibsections may have read / write protections on the memory. Avoid issues...
* SFLAG_CONVERTED: The conversion destination memory is freed after loading the surface
* heap_memory == NULL: Not defined in the extension. Seems to disable client storage effectively
*/
surface->flags &= ~SFLAG_CLIENT;
}
else
{
surface->flags |= SFLAG_CLIENT;
mem = surface->resource.heap_memory;
gl_info->gl_ops.gl.p_glPixelStorei(GL_UNPACK_CLIENT_STORAGE_APPLE, GL_TRUE);
checkGLcall("glPixelStorei(GL_UNPACK_CLIENT_STORAGE_APPLE, GL_TRUE)");
disable_client_storage = TRUE;
}
}
if (format->flags & WINED3DFMT_FLAG_COMPRESSED && mem)
{
GL_EXTCALL(glCompressedTexImage2DARB(surface->texture_target, surface->texture_level,
internal, width, height, 0, surface->resource.size, mem));
checkGLcall("glCompressedTexImage2DARB");
}
else
{
gl_info->gl_ops.gl.p_glTexImage2D(surface->texture_target, surface->texture_level,
internal, width, height, 0, format->glFormat, format->glType, mem);
checkGLcall("glTexImage2D");
}
if (disable_client_storage)
{
gl_info->gl_ops.gl.p_glPixelStorei(GL_UNPACK_CLIENT_STORAGE_APPLE, GL_FALSE);
checkGLcall("glPixelStorei(GL_UNPACK_CLIENT_STORAGE_APPLE, GL_FALSE)");
}
}
/* In D3D the depth stencil dimensions have to be greater than or equal to the
* render target dimensions. With FBOs, the dimensions have to be an exact match. */
/* TODO: We should synchronize the renderbuffer's content with the texture's content. */
......@@ -2991,7 +2914,7 @@ void surface_load_fb_texture(struct wined3d_surface *surface, BOOL srgb)
gl_info = context->gl_info;
device_invalidate_state(device, STATE_FRAMEBUFFER);
surface_prepare_texture(surface, context, srgb);
wined3d_texture_prepare_texture(surface->container, context, srgb);
wined3d_texture_bind_and_dirtify(surface->container, context, srgb);
TRACE("Reading back offscreen render target %p.\n", surface);
......@@ -3009,48 +2932,6 @@ void surface_load_fb_texture(struct wined3d_surface *surface, BOOL srgb)
context_release(context);
}
/* Context activation is done by the caller. */
void surface_prepare_texture(struct wined3d_surface *surface, struct wined3d_context *context, BOOL srgb)
{
struct wined3d_texture *texture = surface->container;
DWORD alloc_flag = srgb ? SFLAG_SRGBALLOCATED : SFLAG_ALLOCATED;
const struct wined3d_format *format = texture->resource.format;
UINT sub_count = texture->level_count * texture->layer_count;
const struct wined3d_color_key_conversion *conversion;
BOOL converted = FALSE;
UINT i;
TRACE("surface %p is a subresource of texture %p.\n", surface, texture);
if (format->convert)
{
converted = TRUE;
}
else if ((conversion = wined3d_format_get_color_key_conversion(texture, TRUE)))
{
converted = TRUE;
format = wined3d_get_format(context->gl_info, conversion->dst_format);
}
wined3d_texture_bind_and_dirtify(texture, context, srgb);
for (i = 0; i < sub_count; ++i)
{
struct wined3d_surface *s = surface_from_resource(texture->sub_resources[i]);
if (s->flags & alloc_flag)
continue;
if (converted)
s->flags |= SFLAG_CONVERTED;
else
s->flags &= ~SFLAG_CONVERTED;
surface_allocate_surface(s, context->gl_info, format, srgb);
s->flags |= alloc_flag;
}
}
void surface_prepare_rb(struct wined3d_surface *surface, const struct wined3d_gl_info *gl_info, BOOL multisample)
{
if (multisample)
......@@ -3952,7 +3833,7 @@ void surface_load_ds_location(struct wined3d_surface *surface, struct wined3d_co
switch (location)
{
case WINED3D_LOCATION_TEXTURE_RGB:
surface_prepare_texture(surface, context, FALSE);
wined3d_texture_prepare_texture(surface->container, context, FALSE);
break;
case WINED3D_LOCATION_RB_MULTISAMPLE:
surface_prepare_rb(surface, gl_info, TRUE);
......@@ -4297,7 +4178,7 @@ static HRESULT surface_load_texture(struct wined3d_surface *surface,
/* TODO: Use already acquired context when possible. */
context = context_acquire(device, NULL);
surface_prepare_texture(surface, context, srgb);
wined3d_texture_prepare_texture(texture, context, srgb);
wined3d_texture_bind_and_dirtify(texture, context, srgb);
if (texture->color_key_flags & WINEDDSD_CKSRCBLT)
......
......@@ -749,6 +749,11 @@ HRESULT CDECL wined3d_texture_update_desc(struct wined3d_texture *texture, UINT
return wined3d_surface_update_desc(surface, gl_info, mem, pitch);
}
void wined3d_texture_prepare_texture(struct wined3d_texture *texture, struct wined3d_context *context, BOOL srgb)
{
texture->texture_ops->texture_prepare_texture(texture, context, srgb);
}
void CDECL wined3d_texture_generate_mipmaps(struct wined3d_texture *texture)
{
/* TODO: Implement filters using GL_SGI_generate_mipmaps. */
......@@ -812,11 +817,122 @@ static void texture2d_sub_resource_cleanup(struct wined3d_resource *sub_resource
wined3d_surface_destroy(surface);
}
/* Context activation is done by the caller. */
static void texture2d_prepare_texture(struct wined3d_texture *texture, struct wined3d_context *context, BOOL srgb)
{
UINT sub_count = texture->level_count * texture->layer_count;
DWORD alloc_flag = srgb ? SFLAG_SRGBALLOCATED : SFLAG_ALLOCATED;
const struct wined3d_format *format = texture->resource.format;
const struct wined3d_gl_info *gl_info = context->gl_info;
const struct wined3d_color_key_conversion *conversion;
BOOL converted = FALSE;
GLenum internal;
UINT i;
TRACE("texture %p, format %s.\n", texture, debug_d3dformat(format->id));
if (format->convert)
{
converted = TRUE;
}
else if ((conversion = wined3d_format_get_color_key_conversion(texture, TRUE)))
{
converted = TRUE;
format = wined3d_get_format(gl_info, conversion->dst_format);
TRACE("Using format %s for color key conversion.\n", debug_d3dformat(format->id));
}
wined3d_texture_bind_and_dirtify(texture, context, srgb);
if (srgb)
internal = format->glGammaInternal;
else if (texture->resource.usage & WINED3DUSAGE_RENDERTARGET
&& wined3d_resource_is_offscreen(&texture->resource))
internal = format->rtInternal;
else
internal = format->glInternal;
if (!internal)
FIXME("No GL internal format for format %s.\n", debug_d3dformat(format->id));
TRACE("internal %#x, format %#x, type %#x.\n", internal, format->glFormat, format->glType);
for (i = 0; i < sub_count; ++i)
{
struct wined3d_surface *surface = surface_from_resource(texture->sub_resources[i]);
GLsizei height = surface->pow2Height;
GLsizei width = surface->pow2Width;
const BYTE *mem = NULL;
if (surface->flags & alloc_flag)
continue;
if (converted)
surface->flags |= SFLAG_CONVERTED;
else
surface->flags &= ~SFLAG_CONVERTED;
if (format->flags & WINED3DFMT_FLAG_HEIGHT_SCALE)
{
height *= format->height_scale.numerator;
height /= format->height_scale.denominator;
}
TRACE("surface %p, target %#x, level %d, width %d, height %d.\n",
surface, surface->texture_target, surface->texture_level, width, height);
if (gl_info->supported[APPLE_CLIENT_STORAGE])
{
if (surface->flags & (SFLAG_NONPOW2 | SFLAG_DIBSECTION | SFLAG_CONVERTED)
|| !surface->resource.heap_memory)
{
/* In some cases we want to disable client storage.
* SFLAG_NONPOW2 has a bigger opengl texture than the client memory, and different pitches
* SFLAG_DIBSECTION: Dibsections may have read / write protections on the memory. Avoid issues...
* SFLAG_CONVERTED: The conversion destination memory is freed after loading the surface
* heap_memory == NULL: Not defined in the extension. Seems to disable client storage effectively
*/
surface->flags &= ~SFLAG_CLIENT;
}
else
{
surface->flags |= SFLAG_CLIENT;
mem = surface->resource.heap_memory;
gl_info->gl_ops.gl.p_glPixelStorei(GL_UNPACK_CLIENT_STORAGE_APPLE, GL_TRUE);
checkGLcall("glPixelStorei(GL_UNPACK_CLIENT_STORAGE_APPLE, GL_TRUE)");
}
}
if (format->flags & WINED3DFMT_FLAG_COMPRESSED && mem)
{
GL_EXTCALL(glCompressedTexImage2DARB(surface->texture_target, surface->texture_level,
internal, width, height, 0, surface->resource.size, mem));
checkGLcall("glCompressedTexImage2DARB");
}
else
{
gl_info->gl_ops.gl.p_glTexImage2D(surface->texture_target, surface->texture_level,
internal, width, height, 0, format->glFormat, format->glType, mem);
checkGLcall("glTexImage2D");
}
if (mem)
{
gl_info->gl_ops.gl.p_glPixelStorei(GL_UNPACK_CLIENT_STORAGE_APPLE, GL_FALSE);
checkGLcall("glPixelStorei(GL_UNPACK_CLIENT_STORAGE_APPLE, GL_FALSE)");
}
surface->flags |= alloc_flag;
}
}
static const struct wined3d_texture_ops texture2d_ops =
{
texture2d_sub_resource_load,
texture2d_sub_resource_add_dirty_region,
texture2d_sub_resource_cleanup,
texture2d_prepare_texture,
};
static ULONG texture_resource_incref(struct wined3d_resource *resource)
......@@ -1145,11 +1261,56 @@ static void texture3d_sub_resource_cleanup(struct wined3d_resource *sub_resource
wined3d_volume_destroy(volume);
}
static void texture3d_prepare_texture(struct wined3d_texture *texture, struct wined3d_context *context, BOOL srgb)
{
DWORD alloc_flag = srgb ? WINED3D_VFLAG_SRGB_ALLOCATED : WINED3D_VFLAG_ALLOCATED;
unsigned int sub_count = texture->level_count * texture->layer_count;
const struct wined3d_format *format = texture->resource.format;
const struct wined3d_gl_info *gl_info = context->gl_info;
unsigned int i;
wined3d_texture_bind_and_dirtify(texture, context, srgb);
for (i = 0; i < sub_count; ++i)
{
struct wined3d_volume *volume = volume_from_resource(texture->sub_resources[i]);
void *mem = NULL;
if (volume->flags & alloc_flag)
continue;
if (gl_info->supported[APPLE_CLIENT_STORAGE] && !format->convert
&& volume_prepare_system_memory(volume))
{
TRACE("Enabling GL_UNPACK_CLIENT_STORAGE_APPLE for volume %p\n", volume);
gl_info->gl_ops.gl.p_glPixelStorei(GL_UNPACK_CLIENT_STORAGE_APPLE, GL_TRUE);
checkGLcall("glPixelStorei(GL_UNPACK_CLIENT_STORAGE_APPLE, GL_TRUE)");
mem = volume->resource.heap_memory;
volume->flags |= WINED3D_VFLAG_CLIENT_STORAGE;
}
GL_EXTCALL(glTexImage3DEXT(GL_TEXTURE_3D, volume->texture_level,
srgb ? format->glGammaInternal : format->glInternal,
volume->resource.width, volume->resource.height, volume->resource.depth,
0, format->glFormat, format->glType, mem));
checkGLcall("glTexImage3D");
if (mem)
{
gl_info->gl_ops.gl.p_glPixelStorei(GL_UNPACK_CLIENT_STORAGE_APPLE, GL_FALSE);
checkGLcall("glPixelStorei(GL_UNPACK_CLIENT_STORAGE_APPLE, GL_FALSE)");
}
volume->flags |= alloc_flag;
}
}
static const struct wined3d_texture_ops texture3d_ops =
{
texture3d_sub_resource_load,
texture3d_sub_resource_add_dirty_region,
texture3d_sub_resource_cleanup,
texture3d_prepare_texture,
};
static HRESULT volumetexture_init(struct wined3d_texture *texture, const struct wined3d_resource_desc *desc,
......
......@@ -27,11 +27,7 @@
WINE_DEFAULT_DEBUG_CHANNEL(d3d_surface);
WINE_DECLARE_DEBUG_CHANNEL(d3d_perf);
#define WINED3D_VFLAG_ALLOCATED 0x00000001
#define WINED3D_VFLAG_SRGB_ALLOCATED 0x00000002
#define WINED3D_VFLAG_CLIENT_STORAGE 0x00000004
static BOOL volume_prepare_system_memory(struct wined3d_volume *volume)
BOOL volume_prepare_system_memory(struct wined3d_volume *volume)
{
if (volume->resource.heap_memory)
return TRUE;
......@@ -44,37 +40,6 @@ static BOOL volume_prepare_system_memory(struct wined3d_volume *volume)
return TRUE;
}
/* Context activation is done by the caller. */
static void wined3d_volume_allocate_texture(struct wined3d_volume *volume,
const struct wined3d_context *context, BOOL srgb)
{
const struct wined3d_gl_info *gl_info = context->gl_info;
const struct wined3d_format *format = volume->resource.format;
void *mem = NULL;
if (gl_info->supported[APPLE_CLIENT_STORAGE] && !format->convert
&& volume_prepare_system_memory(volume))
{
TRACE("Enabling GL_UNPACK_CLIENT_STORAGE_APPLE for volume %p\n", volume);
gl_info->gl_ops.gl.p_glPixelStorei(GL_UNPACK_CLIENT_STORAGE_APPLE, GL_TRUE);
checkGLcall("glPixelStorei(GL_UNPACK_CLIENT_STORAGE_APPLE, GL_TRUE)");
mem = volume->resource.heap_memory;
volume->flags |= WINED3D_VFLAG_CLIENT_STORAGE;
}
GL_EXTCALL(glTexImage3DEXT(GL_TEXTURE_3D, volume->texture_level,
srgb ? format->glGammaInternal : format->glInternal,
volume->resource.width, volume->resource.height, volume->resource.depth,
0, format->glFormat, format->glType, mem));
checkGLcall("glTexImage3D");
if (mem)
{
gl_info->gl_ops.gl.p_glPixelStorei(GL_UNPACK_CLIENT_STORAGE_APPLE, GL_FALSE);
checkGLcall("glPixelStorei(GL_UNPACK_CLIENT_STORAGE_APPLE, GL_FALSE)");
}
}
static void wined3d_volume_get_pitch(const struct wined3d_volume *volume, UINT *row_pitch,
UINT *slice_pitch)
{
......@@ -405,28 +370,9 @@ static void wined3d_volume_load_location(struct wined3d_volume *volume,
/* Context activation is done by the caller. */
void wined3d_volume_load(struct wined3d_volume *volume, struct wined3d_context *context, BOOL srgb_mode)
{
wined3d_texture_bind_and_dirtify(volume->container, context, srgb_mode);
if (srgb_mode)
{
if (!(volume->flags & WINED3D_VFLAG_SRGB_ALLOCATED))
{
wined3d_volume_allocate_texture(volume, context, TRUE);
volume->flags |= WINED3D_VFLAG_SRGB_ALLOCATED;
}
wined3d_volume_load_location(volume, context, WINED3D_LOCATION_TEXTURE_SRGB);
}
else
{
if (!(volume->flags & WINED3D_VFLAG_ALLOCATED))
{
wined3d_volume_allocate_texture(volume, context, FALSE);
volume->flags |= WINED3D_VFLAG_ALLOCATED;
}
wined3d_volume_load_location(volume, context, WINED3D_LOCATION_TEXTURE_RGB);
}
wined3d_texture_prepare_texture(volume->container, context, srgb_mode);
wined3d_volume_load_location(volume, context,
srgb_mode ? WINED3D_LOCATION_TEXTURE_SRGB : WINED3D_LOCATION_TEXTURE_RGB);
}
/* Context activation is done by the caller. */
......
......@@ -2116,6 +2116,8 @@ struct wined3d_texture_ops
void (*texture_sub_resource_add_dirty_region)(struct wined3d_resource *sub_resource,
const struct wined3d_box *dirty_region);
void (*texture_sub_resource_cleanup)(struct wined3d_resource *sub_resource);
void (*texture_prepare_texture)(struct wined3d_texture *texture,
struct wined3d_context *context, BOOL srgb);
};
#define WINED3D_TEXTURE_COND_NP2 0x00000001
......@@ -2170,6 +2172,8 @@ void wined3d_texture_bind_and_dirtify(struct wined3d_texture *texture,
struct wined3d_context *context, BOOL srgb) DECLSPEC_HIDDEN;
void wined3d_texture_load(struct wined3d_texture *texture,
struct wined3d_context *context, BOOL srgb) DECLSPEC_HIDDEN;
void wined3d_texture_prepare_texture(struct wined3d_texture *texture,
struct wined3d_context *context, BOOL srgb) DECLSPEC_HIDDEN;
void wined3d_texture_set_dirty(struct wined3d_texture *texture) DECLSPEC_HIDDEN;
void wined3d_texture_set_swapchain(struct wined3d_texture *texture,
struct wined3d_swapchain *swapchain) DECLSPEC_HIDDEN;
......@@ -2187,6 +2191,10 @@ void wined3d_texture_set_swapchain(struct wined3d_texture *texture,
const char *wined3d_debug_location(DWORD location) DECLSPEC_HIDDEN;
#define WINED3D_VFLAG_ALLOCATED 0x00000001
#define WINED3D_VFLAG_SRGB_ALLOCATED 0x00000002
#define WINED3D_VFLAG_CLIENT_STORAGE 0x00000004
struct wined3d_volume
{
struct wined3d_resource resource;
......@@ -2203,6 +2211,7 @@ static inline struct wined3d_volume *volume_from_resource(struct wined3d_resourc
return CONTAINING_RECORD(resource, struct wined3d_volume, resource);
}
BOOL volume_prepare_system_memory(struct wined3d_volume *volume) DECLSPEC_HIDDEN;
HRESULT wined3d_volume_create(struct wined3d_texture *container, const struct wined3d_resource_desc *desc,
unsigned int level, struct wined3d_volume **volume) DECLSPEC_HIDDEN;
void wined3d_volume_destroy(struct wined3d_volume *volume) DECLSPEC_HIDDEN;
......@@ -2314,8 +2323,6 @@ HRESULT surface_load_location(struct wined3d_surface *surface, DWORD location) D
void surface_modify_ds_location(struct wined3d_surface *surface, DWORD location, UINT w, UINT h) DECLSPEC_HIDDEN;
void surface_prepare_rb(struct wined3d_surface *surface,
const struct wined3d_gl_info *gl_info, BOOL multisample) DECLSPEC_HIDDEN;
void surface_prepare_texture(struct wined3d_surface *surface,
struct wined3d_context *context, BOOL srgb) DECLSPEC_HIDDEN;
void surface_set_compatible_renderbuffer(struct wined3d_surface *surface,
const struct wined3d_surface *rt) DECLSPEC_HIDDEN;
void surface_set_texture_target(struct wined3d_surface *surface, GLenum target, GLint level) DECLSPEC_HIDDEN;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment