From f424a77375e71af0c6f3a8e40351426d3f354582 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B3zef=20Kucia?= Date: Thu, 6 Apr 2017 11:47:51 +0200 Subject: [PATCH] wined3d: Add basic support for rendering to 3D textures. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Józef Kucia Signed-off-by: Henri Verbeet Signed-off-by: Alexandre Julliard --- dlls/wined3d/context.c | 132 ++++++++++++++++++--------------- dlls/wined3d/directx.c | 5 ++ dlls/wined3d/wined3d_private.h | 8 +- 3 files changed, 83 insertions(+), 62 deletions(-) diff --git a/dlls/wined3d/context.c b/dlls/wined3d/context.c index a472a1ed87b..c74f7c0719d 100644 --- a/dlls/wined3d/context.c +++ b/dlls/wined3d/context.c @@ -126,7 +126,6 @@ static void context_attach_gl_texture_fbo(struct wined3d_context *context, if (!resource) { gl_info->fbo_ops.glFramebufferTexture2D(fbo_target, attachment, GL_TEXTURE_2D, 0, 0); - checkGLcall("glFramebufferTexture2D()"); } else if (resource->target == GL_TEXTURE_2D_ARRAY) { @@ -138,14 +137,24 @@ static void context_attach_gl_texture_fbo(struct wined3d_context *context, gl_info->fbo_ops.glFramebufferTextureLayer(fbo_target, attachment, resource->object, resource->level, resource->layer); - checkGLcall("glFramebufferTextureLayer()"); + } + else if (resource->target == GL_TEXTURE_3D) + { + if (!gl_info->fbo_ops.glFramebufferTexture) + { + FIXME("OpenGL implementation doesn't support glFramebufferTexture().\n"); + return; + } + + gl_info->fbo_ops.glFramebufferTexture(fbo_target, attachment, + resource->object, resource->level); } else { gl_info->fbo_ops.glFramebufferTexture2D(fbo_target, attachment, resource->target, resource->object, resource->level); - checkGLcall("glFramebufferTexture2D()"); } + checkGLcall("attach texture to fbo"); } /* Context activation is done by the caller. */ @@ -374,88 +383,93 @@ static inline DWORD context_generate_rt_mask_from_resource(struct wined3d_resour return (1u << 31) | wined3d_texture_get_gl_buffer(texture_from_resource(resource)); } -static inline void context_set_fbo_key_for_surface(const struct wined3d_context *context, - struct wined3d_fbo_entry_key *key, UINT idx, struct wined3d_surface *surface, +static inline void context_set_fbo_key_for_render_target(const struct wined3d_context *context, + struct wined3d_fbo_entry_key *key, unsigned int idx, struct wined3d_rendertarget_info *render_target, DWORD location) { - if (!surface || surface->container->resource.format->id == WINED3DFMT_NULL) + unsigned int sub_resource_idx = render_target->sub_resource_idx; + struct wined3d_resource *resource = render_target->resource; + struct wined3d_texture *texture; + + if (!resource || resource->format->id == WINED3DFMT_NULL || resource->type == WINED3D_RTYPE_BUFFER) { + if (resource && resource->type == WINED3D_RTYPE_BUFFER) + FIXME("Not implemented for %s resources.\n", debug_d3dresourcetype(resource->type)); key->objects[idx].object = 0; key->objects[idx].target = 0; key->objects[idx].level = key->objects[idx].layer = 0; + return; } - else if (surface->current_renderbuffer) + + texture = wined3d_texture_from_resource(resource); + if (resource->type == WINED3D_RTYPE_TEXTURE_2D) { - key->objects[idx].object = surface->current_renderbuffer->id; - key->objects[idx].target = 0; - key->objects[idx].level = key->objects[idx].layer = 0; - key->rb_namespace |= 1 << idx; + struct wined3d_surface *surface = texture->sub_resources[sub_resource_idx].u.surface; + + if (surface->current_renderbuffer) + { + key->objects[idx].object = surface->current_renderbuffer->id; + key->objects[idx].target = 0; + key->objects[idx].level = key->objects[idx].layer = 0; + key->rb_namespace |= 1 << idx; + return; + } + + key->objects[idx].target = surface->texture_target; + key->objects[idx].level = surface->texture_level; + key->objects[idx].layer = surface->texture_layer; } else { - switch (location) - { - case WINED3D_LOCATION_TEXTURE_RGB: - key->objects[idx].object = surface_get_texture_name(surface, context, FALSE); - key->objects[idx].target = surface->texture_target; - key->objects[idx].level = surface->texture_level; - key->objects[idx].layer = surface->texture_layer; - break; + key->objects[idx].target = texture->target; + key->objects[idx].level = sub_resource_idx % texture->level_count; + key->objects[idx].layer = 0; + } - case WINED3D_LOCATION_TEXTURE_SRGB: - key->objects[idx].object = surface_get_texture_name(surface, context, TRUE); - key->objects[idx].target = surface->texture_target; - key->objects[idx].level = surface->texture_level; - key->objects[idx].layer = surface->texture_layer; - break; + switch (location) + { + case WINED3D_LOCATION_TEXTURE_RGB: + key->objects[idx].object = wined3d_texture_get_texture_name(texture, context, FALSE); + break; - case WINED3D_LOCATION_RB_MULTISAMPLE: - key->objects[idx].object = surface->container->rb_multisample; - key->objects[idx].target = 0; - key->objects[idx].level = key->objects[idx].layer = 0; - key->rb_namespace |= 1 << idx; - break; + case WINED3D_LOCATION_TEXTURE_SRGB: + key->objects[idx].object = wined3d_texture_get_texture_name(texture, context, TRUE); + break; - case WINED3D_LOCATION_RB_RESOLVED: - key->objects[idx].object = surface->container->rb_resolved; - key->objects[idx].target = 0; - key->objects[idx].level = key->objects[idx].layer = 0; - key->rb_namespace |= 1 << idx; - break; - } + case WINED3D_LOCATION_RB_MULTISAMPLE: + key->objects[idx].object = texture->rb_multisample; + key->objects[idx].target = 0; + key->objects[idx].level = key->objects[idx].layer = 0; + key->rb_namespace |= 1 << idx; + break; + + case WINED3D_LOCATION_RB_RESOLVED: + key->objects[idx].object = texture->rb_resolved; + key->objects[idx].target = 0; + key->objects[idx].level = key->objects[idx].layer = 0; + key->rb_namespace |= 1 << idx; + break; } } static void context_generate_fbo_key(const struct wined3d_context *context, struct wined3d_fbo_entry_key *key, struct wined3d_rendertarget_info *render_targets, - struct wined3d_surface *depth_stencil, DWORD color_location, + struct wined3d_surface *depth_stencil_surface, DWORD color_location, DWORD ds_location) { + struct wined3d_rendertarget_info depth_stencil = {0}; unsigned int i; key->rb_namespace = 0; - context_set_fbo_key_for_surface(context, key, 0, depth_stencil, ds_location); + if (depth_stencil_surface) + { + depth_stencil.resource = &depth_stencil_surface->container->resource; + depth_stencil.sub_resource_idx = surface_get_sub_resource_idx(depth_stencil_surface); + } + context_set_fbo_key_for_render_target(context, key, 0, &depth_stencil, ds_location); for (i = 0; i < context->gl_info->limits.buffers; ++i) - { - struct wined3d_surface *surface = NULL; - struct wined3d_resource *resource; - - if ((resource = render_targets[i].resource)) - { - if (resource->type == WINED3D_RTYPE_TEXTURE_2D) - { - struct wined3d_texture *texture = wined3d_texture_from_resource(resource); - surface = texture->sub_resources[render_targets[i].sub_resource_idx].u.surface; - } - else - { - FIXME("Not implemented for %s resources.\n", debug_d3dresourcetype(resource->type)); - } - } - - context_set_fbo_key_for_surface(context, key, i + 1, surface, color_location); - } + context_set_fbo_key_for_render_target(context, key, i + 1, &render_targets[i], color_location); } static struct fbo_entry *context_create_fbo_entry(const struct wined3d_context *context, diff --git a/dlls/wined3d/directx.c b/dlls/wined3d/directx.c index 3d70507bd70..0d5a4766ed3 100644 --- a/dlls/wined3d/directx.c +++ b/dlls/wined3d/directx.c @@ -2713,6 +2713,7 @@ static void load_gl_funcs(struct wined3d_gl_info *gl_info) USE_GL_FUNC(glDeleteFramebuffers) USE_GL_FUNC(glDeleteRenderbuffers) USE_GL_FUNC(glFramebufferRenderbuffer) + USE_GL_FUNC(glFramebufferTexture) USE_GL_FUNC(glFramebufferTexture1D) USE_GL_FUNC(glFramebufferTexture2D) USE_GL_FUNC(glFramebufferTexture3D) @@ -3202,6 +3203,7 @@ static void load_gl_funcs(struct wined3d_gl_info *gl_info) USE_GL_FUNC(glEnableVertexAttribArray) /* OpenGL 2.0 */ USE_GL_FUNC(glEndQuery) /* OpenGL 1.5 */ USE_GL_FUNC(glEndTransformFeedback) /* OpenGL 3.0 */ + USE_GL_FUNC(glFramebufferTexture) /* OpenGL 3.2 */ USE_GL_FUNC(glGenBuffers) /* OpenGL 1.5 */ USE_GL_FUNC(glGenQueries) /* OpenGL 1.5 */ USE_GL_FUNC(glGenVertexArrays) /* OpenGL 3.0 */ @@ -3331,6 +3333,7 @@ static void load_gl_funcs(struct wined3d_gl_info *gl_info) MAP_GL_FUNCTION(glEnablei, glEnableIndexedEXT); MAP_GL_FUNCTION(glEnableVertexAttribArray, glEnableVertexAttribArrayARB); MAP_GL_FUNCTION(glEndQuery, glEndQueryARB); + MAP_GL_FUNCTION(glFramebufferTexture, glFramebufferTextureARB); MAP_GL_FUNCTION(glGenBuffers, glGenBuffersARB); MAP_GL_FUNCTION(glGenQueries, glGenQueriesARB); MAP_GL_FUNCTION(glGetActiveUniform, glGetActiveUniformARB); @@ -4221,6 +4224,7 @@ static BOOL wined3d_adapter_init_gl_caps(struct wined3d_adapter *adapter, = gl_info->gl_ops.ext.p_glGetFramebufferAttachmentParameteriv; gl_info->fbo_ops.glBlitFramebuffer = gl_info->gl_ops.ext.p_glBlitFramebuffer; gl_info->fbo_ops.glGenerateMipmap = gl_info->gl_ops.ext.p_glGenerateMipmap; + gl_info->fbo_ops.glFramebufferTexture = gl_info->gl_ops.ext.p_glFramebufferTexture; } else { @@ -4253,6 +4257,7 @@ static BOOL wined3d_adapter_init_gl_caps(struct wined3d_adapter *adapter, if (gl_info->supported[ARB_GEOMETRY_SHADER4]) { + gl_info->fbo_ops.glFramebufferTexture = gl_info->gl_ops.ext.p_glFramebufferTextureARB; gl_info->fbo_ops.glFramebufferTextureLayer = gl_info->gl_ops.ext.p_glFramebufferTextureLayerARB; } if (gl_info->supported[EXT_FRAMEBUFFER_BLIT]) diff --git a/dlls/wined3d/wined3d_private.h b/dlls/wined3d/wined3d_private.h index 4d7b9de12df..29a1d66bc77 100644 --- a/dlls/wined3d/wined3d_private.h +++ b/dlls/wined3d/wined3d_private.h @@ -2261,6 +2261,8 @@ struct wined3d_fbo_ops void (WINE_GLAPI *glDeleteFramebuffers)(GLsizei n, const GLuint *framebuffers); void (WINE_GLAPI *glGenFramebuffers)(GLsizei n, GLuint *framebuffers); GLenum (WINE_GLAPI *glCheckFramebufferStatus)(GLenum target); + void (WINE_GLAPI *glFramebufferTexture)(GLenum target, GLenum attachment, + GLuint texture, GLint level); void (WINE_GLAPI *glFramebufferTexture1D)(GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level); void (WINE_GLAPI *glFramebufferTexture2D)(GLenum target, GLenum attachment, @@ -3980,11 +3982,11 @@ static inline BOOL needs_srgb_write(const struct wined3d_context *context, && fb->render_targets[0] && fb->render_targets[0]->format_flags & WINED3DFMT_FLAG_SRGB_WRITE; } -static inline GLuint surface_get_texture_name(const struct wined3d_surface *surface, +static inline GLuint wined3d_texture_get_texture_name(const struct wined3d_texture *texture, const struct wined3d_context *context, BOOL srgb) { - return srgb && needs_separate_srgb_gl_texture(context, surface->container) - ? surface->container->texture_srgb.name : surface->container->texture_rgb.name; + return srgb && needs_separate_srgb_gl_texture(context, texture) + ? texture->texture_srgb.name : texture->texture_rgb.name; } static inline BOOL can_use_texture_swizzle(const struct wined3d_gl_info *gl_info, const struct wined3d_format *format)