diff --git a/dlls/wined3d/buffer.c b/dlls/wined3d/buffer.c index 857bae6e343..ea584dfcc43 100644 --- a/dlls/wined3d/buffer.c +++ b/dlls/wined3d/buffer.c @@ -1145,7 +1145,7 @@ static HRESULT buffer_init(struct wined3d_buffer *buffer, struct wined3d_device return WINED3DERR_INVALIDCALL; } - hr = resource_init(&buffer->resource, device, WINED3D_RTYPE_BUFFER, WINED3D_GL_RES_TYPE_BUFFER, format, + hr = resource_init(&buffer->resource, device, WINED3D_RTYPE_BUFFER, format, WINED3D_MULTISAMPLE_NONE, 0, usage, pool, size, 1, 1, size, parent, parent_ops, &buffer_resource_ops); if (FAILED(hr)) { diff --git a/dlls/wined3d/resource.c b/dlls/wined3d/resource.c index d5a0041edaa..04b3516c2ba 100644 --- a/dlls/wined3d/resource.c +++ b/dlls/wined3d/resource.c @@ -72,16 +72,96 @@ static void resource_check_usage(DWORD usage) } HRESULT resource_init(struct wined3d_resource *resource, struct wined3d_device *device, - enum wined3d_resource_type type, enum wined3d_gl_resource_type gl_type, const struct wined3d_format *format, + enum wined3d_resource_type type, const struct wined3d_format *format, enum wined3d_multisample_type multisample_type, UINT multisample_quality, DWORD usage, enum wined3d_pool pool, UINT width, UINT height, UINT depth, UINT size, void *parent, const struct wined3d_parent_ops *parent_ops, const struct wined3d_resource_ops *resource_ops) { const struct wined3d *d3d = device->wined3d; + const struct wined3d_gl_info *gl_info = &device->adapter->gl_info; + static const enum wined3d_gl_resource_type gl_resource_types[][3] = + { + /* 0 */ {WINED3D_GL_RES_TYPE_COUNT}, + /* WINED3D_RTYPE_SURFACE */ {WINED3D_GL_RES_TYPE_COUNT}, + /* WINED3D_RTYPE_VOLUME */ {WINED3D_GL_RES_TYPE_COUNT}, + /* WINED3D_RTYPE_TEXTURE */ {WINED3D_GL_RES_TYPE_TEX_2D, + WINED3D_GL_RES_TYPE_TEX_RECT, WINED3D_GL_RES_TYPE_COUNT}, + /* WINED3D_RTYPE_VOLUME_TEXTURE */ {WINED3D_GL_RES_TYPE_TEX_3D, WINED3D_GL_RES_TYPE_COUNT}, + /* WINED3D_RTYPE_CUBE_TEXTURE */ {WINED3D_GL_RES_TYPE_TEX_CUBE, WINED3D_GL_RES_TYPE_COUNT}, + /* WINED3D_RTYPE_BUFFER */ {WINED3D_GL_RES_TYPE_BUFFER, WINED3D_GL_RES_TYPE_COUNT}, + }; + enum wined3d_gl_resource_type gl_type = WINED3D_GL_RES_TYPE_COUNT; + enum wined3d_gl_resource_type base_type = gl_resource_types[type][0]; resource_check_usage(usage); + if (base_type != WINED3D_GL_RES_TYPE_COUNT) + { + unsigned int i; + BOOL tex_2d_ok = FALSE; + + for (i = 0; (gl_type = gl_resource_types[type][i]) != WINED3D_GL_RES_TYPE_COUNT; i++) + { + if ((usage & WINED3DUSAGE_RENDERTARGET) && !(format->flags[gl_type] & WINED3DFMT_FLAG_RENDERTARGET)) + { + WARN("Format %s cannot be used for render targets.\n", debug_d3dformat(format->id)); + continue; + } + if ((usage & WINED3DUSAGE_DEPTHSTENCIL) && + !(format->flags[gl_type] & (WINED3DFMT_FLAG_DEPTH | WINED3DFMT_FLAG_STENCIL))) + { + WARN("Format %s cannot be used for depth/stencil buffers.\n", debug_d3dformat(format->id)); + continue; + } + if ((usage & WINED3DUSAGE_TEXTURE) && !(format->flags[gl_type] & WINED3DFMT_FLAG_TEXTURE)) + { + WARN("Format %s cannot be used for texturing.\n", debug_d3dformat(format->id)); + continue; + } + if (((width & (width - 1)) || (height & (height - 1))) + && !gl_info->supported[ARB_TEXTURE_NON_POWER_OF_TWO] + && !gl_info->supported[WINED3D_GL_NORMALIZED_TEXRECT] + && gl_type == WINED3D_GL_RES_TYPE_TEX_2D) + { + TRACE("Skipping 2D texture type to try texture rectangle.\n"); + tex_2d_ok = TRUE; + continue; + } + break; + } + + if (gl_type == WINED3D_GL_RES_TYPE_COUNT) + { + if (tex_2d_ok) + { + /* Non power of 2 texture and rectangle textures or renderbuffers do not work. + * Use 2D textures, the texture code will pad to a power of 2 size. */ + gl_type = WINED3D_GL_RES_TYPE_TEX_2D; + } + else if (pool == WINED3D_POOL_SCRATCH) + { + /* Needed for proper format information. */ + gl_type = base_type; + } + else + { + WARN("Did not find a suitable GL resource type, resource type, d3d type %u.\n", type); + return WINED3DERR_INVALIDCALL; + } + } + } + + if (base_type != WINED3D_GL_RES_TYPE_COUNT + && (format->flags[base_type] & (WINED3DFMT_FLAG_BLOCKS | WINED3DFMT_FLAG_BLOCKS_NO_VERIFY)) + == WINED3DFMT_FLAG_BLOCKS) + { + UINT width_mask = format->block_width - 1; + UINT height_mask = format->block_height - 1; + if (width & width_mask || height & height_mask) + return WINED3DERR_INVALIDCALL; + } + resource->ref = 1; resource->device = device; resource->type = type; @@ -106,26 +186,6 @@ HRESULT resource_init(struct wined3d_resource *resource, struct wined3d_device * resource->resource_ops = resource_ops; resource->map_binding = WINED3D_LOCATION_SYSMEM; - if (pool != WINED3D_POOL_SCRATCH && type != WINED3D_RTYPE_BUFFER && gl_type < WINED3D_GL_RES_TYPE_COUNT) - { - if ((usage & WINED3DUSAGE_RENDERTARGET) && !(resource->format_flags & WINED3DFMT_FLAG_RENDERTARGET)) - { - WARN("Format %s cannot be used for render targets.\n", debug_d3dformat(format->id)); - return WINED3DERR_INVALIDCALL; - } - if ((usage & WINED3DUSAGE_DEPTHSTENCIL) && - !(resource->format_flags & (WINED3DFMT_FLAG_DEPTH | WINED3DFMT_FLAG_STENCIL))) - { - WARN("Format %s cannot be used for depth/stencil buffers.\n", debug_d3dformat(format->id)); - return WINED3DERR_INVALIDCALL; - } - if ((usage & WINED3DUSAGE_TEXTURE) && !(resource->format_flags & WINED3DFMT_FLAG_TEXTURE)) - { - WARN("Format %s cannot be used for texturing.\n", debug_d3dformat(format->id)); - return WINED3DERR_INVALIDCALL; - } - } - if (size) { if (!wined3d_resource_allocate_sysmem(resource)) diff --git a/dlls/wined3d/surface.c b/dlls/wined3d/surface.c index f4b69e2996f..97b47974339 100644 --- a/dlls/wined3d/surface.c +++ b/dlls/wined3d/surface.c @@ -5459,7 +5459,7 @@ static HRESULT surface_init(struct wined3d_surface *surface, struct wined3d_text else surface->surface_ops = &surface_ops; - if (FAILED(hr = resource_init(&surface->resource, device, WINED3D_RTYPE_SURFACE, WINED3D_GL_RES_TYPE_COUNT, + if (FAILED(hr = resource_init(&surface->resource, device, WINED3D_RTYPE_SURFACE, format, desc->multisample_type, multisample_quality, desc->usage, desc->pool, desc->width, desc->height, 1, resource_size, NULL, &wined3d_null_parent_ops, &surface_resource_ops))) { diff --git a/dlls/wined3d/texture.c b/dlls/wined3d/texture.c index 916bcb2d913..1e039e4128b 100644 --- a/dlls/wined3d/texture.c +++ b/dlls/wined3d/texture.c @@ -29,8 +29,8 @@ WINE_DECLARE_DEBUG_CHANNEL(winediag); static HRESULT wined3d_texture_init(struct wined3d_texture *texture, const struct wined3d_texture_ops *texture_ops, UINT layer_count, UINT level_count, const struct wined3d_resource_desc *desc, DWORD surface_flags, - enum wined3d_gl_resource_type gl_type, struct wined3d_device *device, void *parent, - const struct wined3d_parent_ops *parent_ops, const struct wined3d_resource_ops *resource_ops) + struct wined3d_device *device, void *parent, const struct wined3d_parent_ops *parent_ops, + const struct wined3d_resource_ops *resource_ops) { const struct wined3d_format *format = wined3d_get_format(&device->adapter->gl_info, desc->format); HRESULT hr; @@ -43,16 +43,7 @@ static HRESULT wined3d_texture_init(struct wined3d_texture *texture, const struc debug_d3dusage(desc->usage), debug_d3dpool(desc->pool), desc->width, desc->height, desc->depth, surface_flags, device, parent, parent_ops, resource_ops); - if ((format->flags[gl_type] & (WINED3DFMT_FLAG_BLOCKS | WINED3DFMT_FLAG_BLOCKS_NO_VERIFY)) - == WINED3DFMT_FLAG_BLOCKS) - { - UINT width_mask = format->block_width - 1; - UINT height_mask = format->block_height - 1; - if (desc->width & width_mask || desc->height & height_mask) - return WINED3DERR_INVALIDCALL; - } - - if (FAILED(hr = resource_init(&texture->resource, device, desc->resource_type, gl_type, format, + if (FAILED(hr = resource_init(&texture->resource, device, desc->resource_type, format, desc->multisample_type, desc->multisample_quality, desc->usage, desc->pool, desc->width, desc->height, desc->depth, 0, parent, parent_ops, resource_ops))) { @@ -61,8 +52,8 @@ static HRESULT wined3d_texture_init(struct wined3d_texture *texture, const struc /* DXTn 3D textures are not supported. Do not write the ERR for them. */ if ((desc->format == WINED3DFMT_DXT1 || desc->format == WINED3DFMT_DXT2 || desc->format == WINED3DFMT_DXT3 || desc->format == WINED3DFMT_DXT4 || desc->format == WINED3DFMT_DXT5) - && !(format->flags[gl_type] & WINED3DFMT_FLAG_TEXTURE) && gl_type != WINED3D_GL_RES_TYPE_TEX_3D - && !once++) + && !(format->flags[WINED3D_GL_RES_TYPE_TEX_2D] & WINED3DFMT_FLAG_TEXTURE) + && desc->resource_type != WINED3D_RTYPE_VOLUME_TEXTURE && !once++) ERR_(winediag)("The application tried to create a DXTn texture, but the driver does not support them.\n"); WARN("Failed to initialize resource, returning %#x\n", hr); @@ -1017,7 +1008,7 @@ static HRESULT cubetexture_init(struct wined3d_texture *texture, const struct wi } if (FAILED(hr = wined3d_texture_init(texture, &texture2d_ops, 6, levels, desc, - surface_flags, WINED3D_GL_RES_TYPE_TEX_CUBE, device, parent, parent_ops, &texture_resource_ops))) + surface_flags, device, parent, parent_ops, &texture_resource_ops))) { WARN("Failed to initialize texture, returning %#x\n", hr); return hr; @@ -1076,9 +1067,6 @@ static HRESULT texture_init(struct wined3d_texture *texture, const struct wined3 UINT pow2_width, pow2_height; unsigned int i; HRESULT hr; - enum wined3d_gl_resource_type gl_type; - unsigned int required_flags = 0, ds_flags = WINED3DFMT_FLAG_DEPTH | WINED3DFMT_FLAG_STENCIL; - const struct wined3d_format *format; /* TODO: It should only be possible to create textures for formats * that are reported as supported. */ @@ -1087,7 +1075,6 @@ static HRESULT texture_init(struct wined3d_texture *texture, const struct wined3 WARN("(%p) : Texture cannot be created with a format of WINED3DFMT_UNKNOWN.\n", texture); return WINED3DERR_INVALIDCALL; } - format = wined3d_get_format(gl_info, desc->format); /* Non-power2 support. */ if (gl_info->supported[ARB_TEXTURE_NON_POWER_OF_TWO]) @@ -1138,32 +1125,15 @@ static HRESULT texture_init(struct wined3d_texture *texture, const struct wined3 } } - if (desc->usage & WINED3DUSAGE_TEXTURE) - required_flags |= WINED3DFMT_FLAG_TEXTURE; - if (desc->usage & WINED3DUSAGE_RENDERTARGET) - required_flags |= WINED3DFMT_FLAG_RENDERTARGET; - /* WINED3DUSAGE_DEPTHSTENCIL needs WINED3DFMT_FLAG_DEPTH or WINED3DFMT_FLAG_STENCIL, not both. */ - - if ((format->flags[WINED3D_GL_RES_TYPE_TEX_2D] & required_flags) == required_flags - && (!(desc->usage & WINED3DUSAGE_DEPTHSTENCIL) || (format->flags[WINED3D_GL_RES_TYPE_TEX_2D] & ds_flags)) - && (gl_info->supported[WINED3D_GL_NORMALIZED_TEXRECT] - || (desc->width == pow2_width && desc->height == pow2_height))) - gl_type = WINED3D_GL_RES_TYPE_TEX_2D; - else if ((format->flags[WINED3D_GL_RES_TYPE_TEX_RECT] & required_flags) == required_flags - && (!(desc->usage & WINED3DUSAGE_DEPTHSTENCIL) || (format->flags[WINED3D_GL_RES_TYPE_TEX_RECT] & ds_flags))) - gl_type = WINED3D_GL_RES_TYPE_TEX_RECT; - else - gl_type = WINED3D_GL_RES_TYPE_TEX_2D; /* No error, may be SCRATCH pool or emulated conditional np2. */ - if (FAILED(hr = wined3d_texture_init(texture, &texture2d_ops, 1, levels, desc, - surface_flags, WINED3D_GL_RES_TYPE_TEX_2D, device, parent, parent_ops, &texture_resource_ops))) + surface_flags, device, parent, parent_ops, &texture_resource_ops))) { WARN("Failed to initialize texture, returning %#x.\n", hr); return hr; } /* Precalculated scaling for 'faked' non power of two texture coords. */ - if (gl_type == WINED3D_GL_RES_TYPE_TEX_RECT) + if (texture->resource.gl_type == WINED3D_GL_RES_TYPE_TEX_RECT) { texture->pow2_matrix[0] = (float)desc->width; texture->pow2_matrix[5] = (float)desc->height; @@ -1389,7 +1359,7 @@ static HRESULT volumetexture_init(struct wined3d_texture *texture, const struct } if (FAILED(hr = wined3d_texture_init(texture, &texture3d_ops, 1, levels, desc, - 0, WINED3D_GL_RES_TYPE_TEX_3D, device, parent, parent_ops, &texture_resource_ops))) + 0, device, parent, parent_ops, &texture_resource_ops))) { WARN("Failed to initialize texture, returning %#x.\n", hr); return hr; diff --git a/dlls/wined3d/volume.c b/dlls/wined3d/volume.c index 0f02f340894..424938aa73f 100644 --- a/dlls/wined3d/volume.c +++ b/dlls/wined3d/volume.c @@ -759,8 +759,8 @@ static HRESULT volume_init(struct wined3d_volume *volume, struct wined3d_texture size = wined3d_format_calculate_size(format, device->surface_alignment, desc->width, desc->height, desc->depth); - if (FAILED(hr = resource_init(&volume->resource, device, WINED3D_RTYPE_VOLUME, WINED3D_GL_RES_TYPE_COUNT, - format, WINED3D_MULTISAMPLE_NONE, 0, desc->usage, desc->pool, desc->width, desc->height, desc->depth, + if (FAILED(hr = resource_init(&volume->resource, device, WINED3D_RTYPE_VOLUME, format, + WINED3D_MULTISAMPLE_NONE, 0, desc->usage, desc->pool, desc->width, desc->height, desc->depth, size, NULL, &wined3d_null_parent_ops, &volume_resource_ops))) { WARN("Failed to initialize resource, returning %#x.\n", hr); diff --git a/dlls/wined3d/wined3d_private.h b/dlls/wined3d/wined3d_private.h index 7438f7fc865..dd3122975c6 100644 --- a/dlls/wined3d/wined3d_private.h +++ b/dlls/wined3d/wined3d_private.h @@ -2154,7 +2154,7 @@ static inline ULONG wined3d_resource_decref(struct wined3d_resource *resource) void resource_cleanup(struct wined3d_resource *resource) DECLSPEC_HIDDEN; HRESULT resource_init(struct wined3d_resource *resource, struct wined3d_device *device, - enum wined3d_resource_type type, enum wined3d_gl_resource_type gl_type, const struct wined3d_format *format, + enum wined3d_resource_type type, const struct wined3d_format *format, enum wined3d_multisample_type multisample_type, UINT multisample_quality, DWORD usage, enum wined3d_pool pool, UINT width, UINT height, UINT depth, UINT size, void *parent, const struct wined3d_parent_ops *parent_ops,