wined3d: Add basic support for rendering to 3D textures.

Signed-off-by: Józef Kucia <jkucia@codeweavers.com>
Signed-off-by: Henri Verbeet <hverbeet@codeweavers.com>
Signed-off-by: Alexandre Julliard <julliard@winehq.org>
oldstable
Józef Kucia 2017-04-06 11:47:51 +02:00 committed by Alexandre Julliard
parent 26b7baa0dd
commit f424a77375
3 changed files with 83 additions and 62 deletions

View File

@ -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,

View File

@ -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])

View File

@ -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)