[PATCH 2/5] wined3d: Use dummy textures for all the texture targets.
Matteo Bruni
mbruni at codeweavers.com
Thu Aug 25 18:12:27 CDT 2011
---
dlls/wined3d/context.c | 86 ++++++++++++++++++++++++++++++++++++++--
dlls/wined3d/device.c | 79 +++++++++++++++++++++++++++++++++----
dlls/wined3d/state.c | 4 +-
dlls/wined3d/wined3d_private.h | 5 ++-
4 files changed, 159 insertions(+), 15 deletions(-)
diff --git a/dlls/wined3d/context.c b/dlls/wined3d/context.c
index 2bef879..c50e670 100644
--- a/dlls/wined3d/context.c
+++ b/dlls/wined3d/context.c
@@ -1252,6 +1252,40 @@ static int context_choose_pixel_format(struct wined3d_device *device, HDC hdc,
return iPixelFormat;
}
+/* GL locking is done by the caller */
+static void bind_dummy_textures(const struct wined3d_device *device, struct wined3d_context *context)
+{
+ const struct wined3d_gl_info *gl_info = context->gl_info;
+ unsigned int i, count = min(MAX_COMBINED_SAMPLERS, gl_info->limits.combined_samplers);
+
+ for (i = 0; i < count; ++i)
+ {
+ GL_EXTCALL(glActiveTextureARB(GL_TEXTURE0_ARB + i));
+ checkGLcall("glActiveTextureARB");
+
+ glBindTexture(GL_TEXTURE_2D, device->dummyTextureName[i]);
+ checkGLcall("glBindTexture");
+
+ if (gl_info->supported[ARB_TEXTURE_RECTANGLE])
+ {
+ glBindTexture(GL_TEXTURE_RECTANGLE_ARB, device->dummy_texture_rect[i]);
+ checkGLcall("glBindTexture");
+ }
+
+ if (gl_info->supported[EXT_TEXTURE3D])
+ {
+ glBindTexture(GL_TEXTURE_3D, device->dummy_texture_3d[i]);
+ checkGLcall("glBindTexture");
+ }
+
+ if (gl_info->supported[ARB_TEXTURE_CUBE_MAP])
+ {
+ glBindTexture(GL_TEXTURE_CUBE_MAP, device->dummy_texture_cube[i]);
+ checkGLcall("glBindTexture");
+ }
+ }
+}
+
/* Do not call while under the GL lock. */
struct wined3d_context *context_create(struct wined3d_swapchain *swapchain,
struct wined3d_surface *target, const struct wined3d_format *ds_format)
@@ -1564,6 +1598,12 @@ struct wined3d_context *context_create(struct wined3d_swapchain *swapchain,
}
device->frag_pipe->enable_extension(TRUE);
+ /* If this happens to be the first context for the device, dummy textures
+ * are not created yet. In that case, they will be created (and bound) by
+ * create_dummy_textures right after this context is initialized. */
+ if (device->dummyTextureName[0])
+ bind_dummy_textures(device, ret);
+
LEAVE_GL();
TRACE("Created context %p.\n", ret);
@@ -1911,12 +1951,50 @@ void context_active_texture(struct wined3d_context *context, const struct wined3
void context_bind_texture(struct wined3d_context *context, GLenum target, GLuint name)
{
- glBindTexture(target, name);
- checkGLcall("glBindTexture");
+ DWORD unit = context->active_texture;
+ DWORD old_texture_type = context->texture_type[unit];
+
if (name)
- context->texture_type[context->active_texture] = target;
+ {
+ glBindTexture(target, name);
+ checkGLcall("glBindTexture");
+ }
else
- context->texture_type[context->active_texture] = GL_NONE;
+ {
+ target = GL_NONE;
+ }
+
+ if (old_texture_type != target)
+ {
+ const struct wined3d_device *device = context->swapchain->device;
+
+ switch (old_texture_type)
+ {
+ case GL_NONE:
+ /* nothing to do */
+ break;
+ case GL_TEXTURE_2D:
+ glBindTexture(GL_TEXTURE_2D, device->dummyTextureName[unit]);
+ checkGLcall("glBindTexture");
+ break;
+ case GL_TEXTURE_RECTANGLE_ARB:
+ glBindTexture(GL_TEXTURE_RECTANGLE_ARB, device->dummy_texture_rect[unit]);
+ checkGLcall("glBindTexture");
+ break;
+ case GL_TEXTURE_CUBE_MAP:
+ glBindTexture(GL_TEXTURE_CUBE_MAP, device->dummy_texture_cube[unit]);
+ checkGLcall("glBindTexture");
+ break;
+ case GL_TEXTURE_3D:
+ glBindTexture(GL_TEXTURE_3D, device->dummy_texture_3d[unit]);
+ checkGLcall("glBindTexture");
+ break;
+ default:
+ ERR("Unexpected texture target %#x\n", old_texture_type);
+ }
+
+ context->texture_type[unit] = target;
+ }
}
static void context_set_render_offscreen(struct wined3d_context *context, BOOL offscreen)
diff --git a/dlls/wined3d/device.c b/dlls/wined3d/device.c
index 6b1a48a..8727ec0 100644
--- a/dlls/wined3d/device.c
+++ b/dlls/wined3d/device.c
@@ -970,7 +970,7 @@ out:
static void create_dummy_textures(struct wined3d_device *device, struct wined3d_context *context)
{
const struct wined3d_gl_info *gl_info = &device->adapter->gl_info;
- unsigned int i;
+ unsigned int i, j, count;
/* Under DirectX you can sample even if no texture is bound, whereas
* OpenGL will only allow that when a valid texture is bound.
* We emulate this by creating dummy textures and binding them
@@ -984,25 +984,65 @@ static void create_dummy_textures(struct wined3d_device *device, struct wined3d_
checkGLcall("glPixelStorei(GL_UNPACK_CLIENT_STORAGE_APPLE, GL_FALSE)");
}
- for (i = 0; i < gl_info->limits.textures; ++i)
+ count = min(MAX_COMBINED_SAMPLERS, gl_info->limits.combined_samplers);
+ for (i = 0; i < count; ++i)
{
DWORD color = 0x000000ff;
/* Make appropriate texture active */
context_active_texture(context, gl_info, i);
- /* Generate an opengl texture name */
glGenTextures(1, &device->dummyTextureName[i]);
checkGLcall("glGenTextures");
- TRACE("Dummy Texture %d given name %d.\n", i, device->dummyTextureName[i]);
+ TRACE("Dummy 2D texture %u given name %u.\n", i, device->dummyTextureName[i]);
- /* Generate a dummy 2d texture (not using 1d because they cause many
- * DRI drivers fall back to sw) */
glBindTexture(GL_TEXTURE_2D, device->dummyTextureName[i]);
checkGLcall("glBindTexture");
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, 1, 1, 0, GL_RGBA, GL_UNSIGNED_INT_8_8_8_8, &color);
checkGLcall("glTexImage2D");
+
+ if (gl_info->supported[ARB_TEXTURE_RECTANGLE])
+ {
+ glGenTextures(1, &device->dummy_texture_rect[i]);
+ checkGLcall("glGenTextures");
+ TRACE("Dummy rectangle texture %u given name %u.\n", i, device->dummy_texture_rect[i]);
+
+ glBindTexture(GL_TEXTURE_RECTANGLE_ARB, device->dummy_texture_rect[i]);
+ checkGLcall("glBindTexture");
+
+ glTexImage2D(GL_TEXTURE_RECTANGLE_ARB, 0, GL_RGBA8, 1, 1, 0, GL_RGBA, GL_UNSIGNED_INT_8_8_8_8, &color);
+ checkGLcall("glTexImage2D");
+ }
+
+ if (gl_info->supported[EXT_TEXTURE3D])
+ {
+ glGenTextures(1, &device->dummy_texture_3d[i]);
+ checkGLcall("glGenTextures");
+ TRACE("Dummy 3D texture %u given name %u.\n", i, device->dummy_texture_3d[i]);
+
+ glBindTexture(GL_TEXTURE_3D, device->dummy_texture_3d[i]);
+ checkGLcall("glBindTexture");
+
+ GL_EXTCALL(glTexImage3DEXT(GL_TEXTURE_3D, 0, GL_RGBA8, 1, 1, 1, 0, GL_RGBA, GL_UNSIGNED_INT_8_8_8_8, &color));
+ checkGLcall("glTexImage3D");
+ }
+
+ if (gl_info->supported[ARB_TEXTURE_CUBE_MAP])
+ {
+ glGenTextures(1, &device->dummy_texture_cube[i]);
+ checkGLcall("glGenTextures");
+ TRACE("Dummy cube texture %u given name %u.\n", i, device->dummy_texture_cube[i]);
+
+ glBindTexture(GL_TEXTURE_CUBE_MAP, device->dummy_texture_cube[i]);
+ checkGLcall("glBindTexture");
+
+ for (j = GL_TEXTURE_CUBE_MAP_POSITIVE_X; j <= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z; ++j)
+ {
+ glTexImage2D(j, 0, GL_RGBA8, 1, 1, 0, GL_RGBA, GL_UNSIGNED_INT_8_8_8_8, &color);
+ checkGLcall("glTexImage2D");
+ }
+ }
}
if (gl_info->supported[APPLE_CLIENT_STORAGE])
@@ -1018,11 +1058,34 @@ static void create_dummy_textures(struct wined3d_device *device, struct wined3d_
/* Context activation is done by the caller. */
static void destroy_dummy_textures(struct wined3d_device *device, const struct wined3d_gl_info *gl_info)
{
+ unsigned int count = min(MAX_COMBINED_SAMPLERS, gl_info->limits.combined_samplers);
+
ENTER_GL();
- glDeleteTextures(gl_info->limits.textures, device->dummyTextureName);
- checkGLcall("glDeleteTextures(gl_info->limits.textures, device->dummyTextureName)");
+ if (gl_info->supported[ARB_TEXTURE_CUBE_MAP])
+ {
+ glDeleteTextures(count, device->dummy_texture_cube);
+ checkGLcall("glDeleteTextures(count, device->dummy_texture_cube)");
+ }
+
+ if (gl_info->supported[EXT_TEXTURE3D])
+ {
+ glDeleteTextures(count, device->dummy_texture_3d);
+ checkGLcall("glDeleteTextures(count, device->dummy_texture_3d)");
+ }
+
+ if (gl_info->supported[ARB_TEXTURE_RECTANGLE])
+ {
+ glDeleteTextures(count, device->dummy_texture_rect);
+ checkGLcall("glDeleteTextures(count, device->dummy_texture_rect)");
+ }
+
+ glDeleteTextures(count, device->dummyTextureName);
+ checkGLcall("glDeleteTextures(count, device->dummyTextureName)");
LEAVE_GL();
+ memset(device->dummy_texture_cube, 0, gl_info->limits.textures * sizeof(*device->dummy_texture_cube));
+ memset(device->dummy_texture_3d, 0, gl_info->limits.textures * sizeof(*device->dummy_texture_3d));
+ memset(device->dummy_texture_rect, 0, gl_info->limits.textures * sizeof(*device->dummy_texture_rect));
memset(device->dummyTextureName, 0, gl_info->limits.textures * sizeof(*device->dummyTextureName));
}
diff --git a/dlls/wined3d/state.c b/dlls/wined3d/state.c
index b777432..1535e3a 100644
--- a/dlls/wined3d/state.c
+++ b/dlls/wined3d/state.c
@@ -3566,7 +3566,7 @@ static void sampler(struct wined3d_context *context, const struct wined3d_state
if (!(texture->flags & WINED3D_TEXTURE_POW2_MAT_IDENT))
device->shader_backend->shader_load_np2fixup_constants(device->shader_priv, gl_info, state);
}
- else if (mapped_stage < gl_info->limits.textures)
+ else
{
if (sampler < state->lowest_disabled_stage)
{
@@ -3578,7 +3578,7 @@ static void sampler(struct wined3d_context *context, const struct wined3d_state
state_alpha(context, state, WINED3DRS_COLORKEYENABLE);
}
} /* Otherwise tex_colorop disables the stage */
- context_bind_texture(context, GL_TEXTURE_2D, device->dummyTextureName[sampler]);
+ context_bind_texture(context, GL_NONE, 0);
}
}
diff --git a/dlls/wined3d/wined3d_private.h b/dlls/wined3d/wined3d_private.h
index 0fe5712..56c939a 100644
--- a/dlls/wined3d/wined3d_private.h
+++ b/dlls/wined3d/wined3d_private.h
@@ -1722,7 +1722,10 @@ struct wined3d_device
struct wined3d_surface *logo_surface;
/* Textures for when no other textures are mapped */
- UINT dummyTextureName[MAX_TEXTURES];
+ UINT dummyTextureName[MAX_COMBINED_SAMPLERS];
+ UINT dummy_texture_rect[MAX_COMBINED_SAMPLERS];
+ UINT dummy_texture_3d[MAX_COMBINED_SAMPLERS];
+ UINT dummy_texture_cube[MAX_COMBINED_SAMPLERS];
/* DirectDraw stuff */
DWORD ddraw_width, ddraw_height;
--
1.7.3.4
More information about the wine-patches
mailing list