HRESULT CDECL wined3d_texture_create(struct wined3d_device *device, const struct wined3d_resource_desc *desc, UINT level_count, DWORD surface_flags, void *parent, const struct wined3d_parent_ops *parent_ops, struct wined3d_texture **texture) { struct wined3d_texture *object; HRESULT hr; TRACE("device %p, desc %p, level_count %u, surface_flags %#x, parent %p, parent_ops %p, texture %p.\n", device, desc, level_count, surface_flags, parent, parent_ops, texture); if (!(object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*object)))) return E_OUTOFMEMORY; switch (desc->resource_type) { case WINED3D_RTYPE_TEXTURE: hr = texture_init(object, desc, level_count, surface_flags, device, parent, parent_ops); break; case WINED3D_RTYPE_VOLUME_TEXTURE: hr = volumetexture_init(object, desc, level_count, device, parent, parent_ops); break; case WINED3D_RTYPE_CUBE_TEXTURE: hr = cubetexture_init(object, desc, level_count, surface_flags, device, parent, parent_ops); break; default: ERR("Invalid resource type %s.\n", debug_d3dresourcetype(desc->resource_type)); hr = WINED3DERR_INVALIDCALL; break; } if (FAILED(hr)) { WARN("Failed to initialize texture, returning %#x.\n", hr); HeapFree(GetProcessHeap(), 0, object); return hr; } TRACE("Created texture %p.\n", object); *texture = object; return WINED3D_OK; }
void wined3d_rendertarget_view_validate_location(struct wined3d_rendertarget_view *view, DWORD location) { struct wined3d_resource *resource = view->resource; unsigned int i, sub_resource_idx, layer_count; struct wined3d_texture *texture; if (resource->type == WINED3D_RTYPE_BUFFER) { FIXME("Not implemented for resources %s.\n", debug_d3dresourcetype(resource->type)); return; } texture = texture_from_resource(resource); sub_resource_idx = view->sub_resource_idx; layer_count = resource->type != WINED3D_RTYPE_TEXTURE_3D ? view->layer_count : 1; for (i = 0; i < layer_count; ++i, sub_resource_idx += texture->level_count) wined3d_texture_validate_location(texture, sub_resource_idx, location); }
void wined3d_unordered_access_view_clear_uint(struct wined3d_unordered_access_view *view, const struct wined3d_uvec4 *clear_value, struct wined3d_context *context) { const struct wined3d_gl_info *gl_info = context->gl_info; const struct wined3d_format *format; struct wined3d_resource *resource; struct wined3d_buffer *buffer; unsigned int offset, size; resource = view->resource; if (resource->type != WINED3D_RTYPE_BUFFER) { FIXME("Not implemented for %s resources.\n", debug_d3dresourcetype(resource->type)); return; } if (!gl_info->supported[ARB_CLEAR_BUFFER_OBJECT]) { FIXME("OpenGL implementation does not support ARB_clear_buffer_object.\n"); return; } format = view->format; if (format->id != WINED3DFMT_R32_UINT && format->id != WINED3DFMT_R32_SINT && format->id != WINED3DFMT_R32G32B32A32_UINT && format->id != WINED3DFMT_R32G32B32A32_SINT) { FIXME("Not implemented for format %s.\n", debug_d3dformat(format->id)); return; } buffer = buffer_from_resource(resource); wined3d_buffer_load_location(buffer, context, WINED3D_LOCATION_BUFFER); wined3d_unordered_access_view_invalidate_location(view, ~WINED3D_LOCATION_BUFFER); get_buffer_view_range(buffer, &view->desc, format, &offset, &size); context_bind_bo(context, buffer->buffer_type_hint, buffer->buffer_object); GL_EXTCALL(glClearBufferSubData(buffer->buffer_type_hint, format->glInternal, offset, size, format->glFormat, format->glType, clear_value)); checkGLcall("clear unordered access view"); }
HRESULT CDECL wined3d_rendertarget_view_create_from_sub_resource(struct wined3d_texture *texture, unsigned int sub_resource_idx, void *parent, const struct wined3d_parent_ops *parent_ops, struct wined3d_rendertarget_view **view) { struct wined3d_resource *sub_resource; TRACE("texture %p, sub_resource_idx %u, parent %p, parent_ops %p, view %p.\n", texture, sub_resource_idx, parent, parent_ops, view); if (!(sub_resource = wined3d_texture_get_sub_resource(texture, sub_resource_idx))) return WINED3DERR_INVALIDCALL; if (sub_resource->type != WINED3D_RTYPE_SURFACE) { FIXME("Not implemented for %s resources.\n", debug_d3dresourcetype(texture->resource.type)); return WINED3DERR_INVALIDCALL; } return wined3d_rendertarget_view_create_from_surface(surface_from_resource(sub_resource), parent, parent_ops, view); }
static void wined3d_render_target_view_cs_init(void *object) { struct wined3d_rendertarget_view *view = object; struct wined3d_resource *resource = view->resource; const struct wined3d_view_desc *desc = &view->desc; if (resource->type == WINED3D_RTYPE_BUFFER) { FIXME("Not implemented for resources %s.\n", debug_d3dresourcetype(resource->type)); } else { struct wined3d_texture *texture = texture_from_resource(resource); unsigned int depth_or_layer_count; if (resource->type == WINED3D_RTYPE_TEXTURE_3D) depth_or_layer_count = wined3d_texture_get_level_depth(texture, desc->u.texture.level_idx); else depth_or_layer_count = texture->layer_count; if (resource->format->id != view->format->id || (view->layer_count != 1 && view->layer_count != depth_or_layer_count)) { if (resource->format->gl_view_class != view->format->gl_view_class) { FIXME("Render target view not supported, resource format %s, view format %s.\n", debug_d3dformat(resource->format->id), debug_d3dformat(view->format->id)); return; } if (texture->swapchain && texture->swapchain->desc.backbuffer_count > 1) { FIXME("Swapchain views not supported.\n"); return; } create_texture_view(&view->gl_view, texture->target, desc, texture, view->format); } } }
HRESULT resource_init(struct wined3d_resource *resource, struct wined3d_device *device, 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) { enum wined3d_gl_resource_type base_type = WINED3D_GL_RES_TYPE_COUNT; enum wined3d_gl_resource_type gl_type = WINED3D_GL_RES_TYPE_COUNT; const struct wined3d_gl_info *gl_info = &device->adapter->gl_info; BOOL tex_2d_ok = FALSE; unsigned int i; static const struct { enum wined3d_resource_type type; DWORD cube_usage; enum wined3d_gl_resource_type gl_type; } resource_types[] = { {WINED3D_RTYPE_BUFFER, 0, WINED3D_GL_RES_TYPE_BUFFER}, {WINED3D_RTYPE_TEXTURE_2D, 0, WINED3D_GL_RES_TYPE_TEX_2D}, {WINED3D_RTYPE_TEXTURE_2D, 0, WINED3D_GL_RES_TYPE_TEX_RECT}, {WINED3D_RTYPE_TEXTURE_2D, 0, WINED3D_GL_RES_TYPE_RB}, {WINED3D_RTYPE_TEXTURE_2D, WINED3DUSAGE_LEGACY_CUBEMAP, WINED3D_GL_RES_TYPE_TEX_CUBE}, {WINED3D_RTYPE_TEXTURE_3D, 0, WINED3D_GL_RES_TYPE_TEX_3D}, }; resource_check_usage(usage); for (i = 0; i < ARRAY_SIZE(resource_types); ++i) { if (resource_types[i].type != type || resource_types[i].cube_usage != (usage & WINED3DUSAGE_LEGACY_CUBEMAP)) continue; gl_type = resource_types[i].gl_type; if (base_type == WINED3D_GL_RES_TYPE_COUNT) base_type = gl_type; 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 (wined3d_settings.offscreen_rendering_mode == ORM_FBO && usage & (WINED3DUSAGE_RENDERTARGET | WINED3DUSAGE_DEPTHSTENCIL) && !(format->flags[gl_type] & WINED3DFMT_FLAG_FBO_ATTACHABLE)) { WARN("Render target or depth stencil is not FBO attachable.\n"); 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 (base_type != WINED3D_GL_RES_TYPE_COUNT && i == ARRAY_SIZE(resource_types)) { 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 for resource type %s.\n", debug_d3dresourcetype(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; resource->gl_type = gl_type; resource->format = format; if (gl_type < WINED3D_GL_RES_TYPE_COUNT) resource->format_flags = format->flags[gl_type]; resource->multisample_type = multisample_type; resource->multisample_quality = multisample_quality; resource->usage = usage; resource->pool = pool; resource->access_flags = resource_access_from_pool(pool); if (usage & WINED3DUSAGE_DYNAMIC) resource->access_flags |= WINED3D_RESOURCE_ACCESS_CPU; resource->width = width; resource->height = height; resource->depth = depth; resource->size = size; resource->priority = 0; resource->parent = parent; resource->parent_ops = parent_ops; resource->resource_ops = resource_ops; resource->map_binding = WINED3D_LOCATION_SYSMEM; if (size) { if (!wined3d_resource_allocate_sysmem(resource)) { ERR("Failed to allocate system memory.\n"); return E_OUTOFMEMORY; } } else { resource->heap_memory = NULL; } if (!(usage & WINED3DUSAGE_PRIVATE)) { /* Check that we have enough video ram left */ if (pool == WINED3D_POOL_DEFAULT && device->wined3d->flags & WINED3D_VIDMEM_ACCOUNTING) { if (size > wined3d_device_get_available_texture_mem(device)) { ERR("Out of adapter memory\n"); wined3d_resource_free_sysmem(resource); return WINED3DERR_OUTOFVIDEOMEMORY; } adapter_adjust_memory(device->adapter, size); } device_resource_add(device, resource); } return WINED3D_OK; }
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, 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; TRACE("texture %p, texture_ops %p, layer_count %u, level_count %u, resource_type %s, format %s, " "multisample_type %#x, multisample_quality %#x, usage %s, pool %s, width %u, height %u, depth %u, " "device %p, parent %p, parent_ops %p, resource_ops %p.\n", texture, texture_ops, layer_count, level_count, debug_d3dresourcetype(desc->resource_type), debug_d3dformat(desc->format), desc->multisample_type, desc->multisample_quality, debug_d3dusage(desc->usage), debug_d3dpool(desc->pool), desc->width, desc->height, desc->depth, device, parent, parent_ops, resource_ops); if ((format->flags & (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, format, desc->multisample_type, desc->multisample_quality, desc->usage, desc->pool, desc->width, desc->height, desc->depth, 0, parent, parent_ops, resource_ops))) { static unsigned int once; if ((desc->format == WINED3DFMT_DXT1 || desc->format == WINED3DFMT_DXT2 || desc->format == WINED3DFMT_DXT3 || desc->format == WINED3DFMT_DXT4 || desc->format == WINED3DFMT_DXT5) && !(format->flags & WINED3DFMT_FLAG_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); return hr; } wined3d_resource_update_draw_binding(&texture->resource); texture->texture_ops = texture_ops; texture->sub_resources = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, level_count * layer_count * sizeof(*texture->sub_resources)); if (!texture->sub_resources) { ERR("Failed to allocate sub-resource array.\n"); resource_cleanup(&texture->resource); return E_OUTOFMEMORY; } texture->layer_count = layer_count; texture->level_count = level_count; texture->filter_type = (desc->usage & WINED3DUSAGE_AUTOGENMIPMAP) ? WINED3D_TEXF_LINEAR : WINED3D_TEXF_NONE; texture->lod = 0; texture->flags = WINED3D_TEXTURE_POW2_MAT_IDENT; if (texture->resource.format->flags & WINED3DFMT_FLAG_FILTERING) { texture->min_mip_lookup = minMipLookup; texture->mag_lookup = magLookup; } else { texture->min_mip_lookup = minMipLookup_noFilter; texture->mag_lookup = magLookup_noFilter; } return WINED3D_OK; }