static HRESULT d3d_texture3d_init(struct d3d_texture3d *texture, struct d3d_device *device, const D3D11_TEXTURE3D_DESC *desc, const D3D11_SUBRESOURCE_DATA *data) { struct wined3d_resource_desc wined3d_desc; unsigned int levels; HRESULT hr; texture->ID3D11Texture3D_iface.lpVtbl = &d3d11_texture3d_vtbl; texture->ID3D10Texture3D_iface.lpVtbl = &d3d10_texture3d_vtbl; texture->refcount = 1; wined3d_mutex_lock(); wined3d_private_store_init(&texture->private_store); texture->desc = *desc; wined3d_desc.resource_type = WINED3D_RTYPE_TEXTURE_3D; wined3d_desc.format = wined3dformat_from_dxgi_format(desc->Format); wined3d_desc.multisample_type = WINED3D_MULTISAMPLE_NONE; wined3d_desc.multisample_quality = 0; wined3d_desc.usage = wined3d_usage_from_d3d11(desc->BindFlags, desc->Usage); wined3d_desc.pool = WINED3D_POOL_DEFAULT; wined3d_desc.width = desc->Width; wined3d_desc.height = desc->Height; wined3d_desc.depth = desc->Depth; wined3d_desc.size = 0; levels = desc->MipLevels ? desc->MipLevels : wined3d_log2i(max(max(desc->Width, desc->Height), desc->Depth)) + 1; if (FAILED(hr = wined3d_texture_create(device->wined3d_device, &wined3d_desc, 1, levels, 0, (struct wined3d_sub_resource_data *)data, texture, &d3d_texture3d_wined3d_parent_ops, &texture->wined3d_texture))) { WARN("Failed to create wined3d texture, hr %#x.\n", hr); wined3d_private_store_cleanup(&texture->private_store); wined3d_mutex_unlock(); if (hr == WINED3DERR_INVALIDCALL) hr = E_INVALIDARG; return hr; } wined3d_mutex_unlock(); texture->desc.MipLevels = levels; texture->device = &device->ID3D11Device_iface; ID3D11Device_AddRef(texture->device); return S_OK; }
static HRESULT d3d_texture2d_init(struct d3d_texture2d *texture, struct d3d_device *device, const D3D11_TEXTURE2D_DESC *desc, const D3D11_SUBRESOURCE_DATA *data) { struct wined3d_resource_desc wined3d_desc; unsigned int levels; HRESULT hr; texture->ID3D11Texture2D_iface.lpVtbl = &d3d11_texture2d_vtbl; texture->ID3D10Texture2D_iface.lpVtbl = &d3d10_texture2d_vtbl; texture->refcount = 1; wined3d_mutex_lock(); wined3d_private_store_init(&texture->private_store); texture->desc = *desc; if (desc->ArraySize != 1) FIXME("Array textures not implemented.\n"); if (desc->SampleDesc.Count > 1) FIXME("Multisampled textures not implemented.\n"); wined3d_desc.resource_type = WINED3D_RTYPE_TEXTURE; wined3d_desc.format = wined3dformat_from_dxgi_format(desc->Format); wined3d_desc.multisample_type = desc->SampleDesc.Count > 1 ? desc->SampleDesc.Count : WINED3D_MULTISAMPLE_NONE; wined3d_desc.multisample_quality = desc->SampleDesc.Quality; wined3d_desc.usage = wined3d_usage_from_d3d11(desc->BindFlags, desc->Usage); wined3d_desc.pool = WINED3D_POOL_DEFAULT; wined3d_desc.width = desc->Width; wined3d_desc.height = desc->Height; wined3d_desc.depth = 1; wined3d_desc.size = 0; levels = desc->MipLevels ? desc->MipLevels : wined3d_log2i(max(desc->Width, desc->Height)) + 1; if (FAILED(hr = wined3d_texture_create(device->wined3d_device, &wined3d_desc, levels, 0, (struct wined3d_sub_resource_data *)data, texture, &d3d_texture2d_wined3d_parent_ops, &texture->wined3d_texture))) { WARN("Failed to create wined3d texture, hr %#x.\n", hr); wined3d_private_store_cleanup(&texture->private_store); wined3d_mutex_unlock(); return hr; } texture->desc.MipLevels = levels; if (desc->MipLevels == 1 && desc->ArraySize == 1) { IWineDXGIDevice *wine_device; if (FAILED(hr = ID3D10Device1_QueryInterface(&device->ID3D10Device1_iface, &IID_IWineDXGIDevice, (void **)&wine_device))) { ERR("Device should implement IWineDXGIDevice.\n"); wined3d_texture_decref(texture->wined3d_texture); wined3d_mutex_unlock(); return E_FAIL; } hr = IWineDXGIDevice_create_surface(wine_device, wined3d_texture_get_resource(texture->wined3d_texture), 0, NULL, (IUnknown *)&texture->ID3D10Texture2D_iface, (void **)&texture->dxgi_surface); IWineDXGIDevice_Release(wine_device); if (FAILED(hr)) { ERR("Failed to create DXGI surface, returning %#x\n", hr); texture->dxgi_surface = NULL; wined3d_texture_decref(texture->wined3d_texture); wined3d_mutex_unlock(); return hr; } } wined3d_mutex_unlock(); texture->device = &device->ID3D11Device_iface; ID3D11Device_AddRef(texture->device); return S_OK; }
HRESULT volumetexture_init(IWineD3DVolumeTextureImpl *texture, UINT width, UINT height, UINT depth, UINT levels, IWineD3DDeviceImpl *device, DWORD usage, WINED3DFORMAT format, WINED3DPOOL pool, IUnknown *parent, const struct wined3d_parent_ops *parent_ops #ifdef VBOX_WITH_WDDM , HANDLE *shared_handle , void **pavClientMem #endif ) { const struct wined3d_gl_info *gl_info = &device->adapter->gl_info; const struct wined3d_format_desc *format_desc = getFormatDescEntry(format, gl_info); UINT tmp_w, tmp_h, tmp_d; unsigned int i; HRESULT hr; #ifdef VBOX_WITH_WDDM if (shared_handle) { ERR("shared handle support for volume textures not impemented yet, ignoring!"); } #endif /* TODO: It should only be possible to create textures for formats * that are reported as supported. */ if (WINED3DFMT_UNKNOWN >= format) { WARN("(%p) : Texture cannot be created with a format of WINED3DFMT_UNKNOWN.\n", texture); return WINED3DERR_INVALIDCALL; } if (!gl_info->supported[EXT_TEXTURE3D]) { WARN("(%p) : Texture cannot be created - no volume texture support.\n", texture); return WINED3DERR_INVALIDCALL; } /* Calculate levels for mip mapping. */ if (usage & WINED3DUSAGE_AUTOGENMIPMAP) { if (!gl_info->supported[SGIS_GENERATE_MIPMAP]) { WARN("No mipmap generation support, returning D3DERR_INVALIDCALL.\n"); return WINED3DERR_INVALIDCALL; } if (levels > 1) { WARN("D3DUSAGE_AUTOGENMIPMAP is set, and level count > 1, returning D3DERR_INVALIDCALL.\n"); return WINED3DERR_INVALIDCALL; } levels = 1; } else if (!levels) { levels = wined3d_log2i(max(max(width, height), depth)) + 1; TRACE("Calculated levels = %u.\n", levels); } texture->lpVtbl = &IWineD3DVolumeTexture_Vtbl; hr = basetexture_init((IWineD3DBaseTextureImpl *)texture, levels, WINED3DRTYPE_VOLUMETEXTURE, device, 0, usage, format_desc, pool, parent, parent_ops #ifdef VBOX_WITH_WDDM , shared_handle, pavClientMem #endif ); if (FAILED(hr)) { WARN("Failed to initialize basetexture, returning %#x.\n", hr); return hr; } /* Is NP2 support for volumes needed? */ texture->baseTexture.pow2Matrix[0] = 1.0f; texture->baseTexture.pow2Matrix[5] = 1.0f; texture->baseTexture.pow2Matrix[10] = 1.0f; texture->baseTexture.pow2Matrix[15] = 1.0f; /* Generate all the surfaces. */ tmp_w = width; tmp_h = height; tmp_d = depth; for (i = 0; i < texture->baseTexture.levels; ++i) { /* Create the volume. */ #ifdef VBOX_WITH_WDDM hr = IWineD3DDeviceParent_CreateVolume(device->device_parent, parent, tmp_w, tmp_h, tmp_d, format, pool, usage, &texture->volumes[i] , shared_handle, pavClientMem ? pavClientMem[i] : NULL); #else hr = IWineD3DDeviceParent_CreateVolume(device->device_parent, parent, tmp_w, tmp_h, tmp_d, format, pool, usage, &texture->volumes[i]); #endif if (FAILED(hr)) { ERR("Creating a volume for the volume texture failed, hr %#x.\n", hr); texture->volumes[i] = NULL; volumetexture_cleanup(texture); return hr; } /* Set its container to this texture. */ IWineD3DVolume_SetContainer(texture->volumes[i], (IWineD3DBase *)texture); /* Calculate the next mipmap level. */ tmp_w = max(1, tmp_w >> 1); tmp_h = max(1, tmp_h >> 1); tmp_d = max(1, tmp_d >> 1); } texture->baseTexture.internal_preload = volumetexture_internal_preload; return WINED3D_OK; }
HRESULT texture_init(IWineD3DBaseTextureImpl *texture, UINT width, UINT height, UINT levels, IWineD3DDeviceImpl *device, DWORD usage, enum wined3d_format_id format_id, WINED3DPOOL pool, void *parent, const struct wined3d_parent_ops *parent_ops) { const struct wined3d_gl_info *gl_info = &device->adapter->gl_info; const struct wined3d_format *format = wined3d_get_format(gl_info, format_id); UINT pow2_width, pow2_height; UINT tmp_w, tmp_h; unsigned int i; HRESULT hr; /* TODO: It should only be possible to create textures for formats * that are reported as supported. */ if (WINED3DFMT_UNKNOWN >= format_id) { WARN("(%p) : Texture cannot be created with a format of WINED3DFMT_UNKNOWN.\n", texture); return WINED3DERR_INVALIDCALL; } /* Non-power2 support. */ if (gl_info->supported[ARB_TEXTURE_NON_POWER_OF_TWO]) { pow2_width = width; pow2_height = height; } else { /* Find the nearest pow2 match. */ pow2_width = pow2_height = 1; while (pow2_width < width) pow2_width <<= 1; while (pow2_height < height) pow2_height <<= 1; if (pow2_width != width || pow2_height != height) { if (levels > 1) { WARN("Attempted to create a mipmapped np2 texture without unconditional np2 support.\n"); return WINED3DERR_INVALIDCALL; } levels = 1; } } /* Calculate levels for mip mapping. */ if (usage & WINED3DUSAGE_AUTOGENMIPMAP) { if (!gl_info->supported[SGIS_GENERATE_MIPMAP]) { WARN("No mipmap generation support, returning WINED3DERR_INVALIDCALL.\n"); return WINED3DERR_INVALIDCALL; } if (levels > 1) { WARN("D3DUSAGE_AUTOGENMIPMAP is set, and level count > 1, returning WINED3DERR_INVALIDCALL.\n"); return WINED3DERR_INVALIDCALL; } levels = 1; } else if (!levels) { levels = wined3d_log2i(max(width, height)) + 1; TRACE("Calculated levels = %u.\n", levels); } texture->lpVtbl = &IWineD3DTexture_Vtbl; hr = basetexture_init((IWineD3DBaseTextureImpl *)texture, &texture_ops, 1, levels, WINED3DRTYPE_TEXTURE, device, usage, format, pool, parent, parent_ops, &texture_resource_ops); if (FAILED(hr)) { WARN("Failed to initialize basetexture, returning %#x.\n", hr); return hr; } /* Precalculated scaling for 'faked' non power of two texture coords. * Second also don't use ARB_TEXTURE_RECTANGLE in case the surface format is P8 and EXT_PALETTED_TEXTURE * is used in combination with texture uploads (RTL_READTEX). The reason is that EXT_PALETTED_TEXTURE * doesn't work in combination with ARB_TEXTURE_RECTANGLE. */ if (gl_info->supported[WINED3D_GL_NORMALIZED_TEXRECT] && (width != pow2_width || height != pow2_height)) { texture->baseTexture.pow2Matrix[0] = 1.0f; texture->baseTexture.pow2Matrix[5] = 1.0f; texture->baseTexture.pow2Matrix[10] = 1.0f; texture->baseTexture.pow2Matrix[15] = 1.0f; texture->baseTexture.target = GL_TEXTURE_2D; texture->baseTexture.cond_np2 = TRUE; texture->baseTexture.minMipLookup = minMipLookup_noFilter; } else if (gl_info->supported[ARB_TEXTURE_RECTANGLE] && (width != pow2_width || height != pow2_height) && !(format->id == WINED3DFMT_P8_UINT && gl_info->supported[EXT_PALETTED_TEXTURE] && wined3d_settings.rendertargetlock_mode == RTL_READTEX)) { if ((width != 1) || (height != 1)) texture->baseTexture.pow2Matrix_identity = FALSE; texture->baseTexture.pow2Matrix[0] = (float)width; texture->baseTexture.pow2Matrix[5] = (float)height; texture->baseTexture.pow2Matrix[10] = 1.0f; texture->baseTexture.pow2Matrix[15] = 1.0f; texture->baseTexture.target = GL_TEXTURE_RECTANGLE_ARB; texture->baseTexture.cond_np2 = TRUE; if (texture->resource.format->flags & WINED3DFMT_FLAG_FILTERING) { texture->baseTexture.minMipLookup = minMipLookup_noMip; } else { texture->baseTexture.minMipLookup = minMipLookup_noFilter; } } else { if ((width != pow2_width) || (height != pow2_height)) { texture->baseTexture.pow2Matrix_identity = FALSE; texture->baseTexture.pow2Matrix[0] = (((float)width) / ((float)pow2_width)); texture->baseTexture.pow2Matrix[5] = (((float)height) / ((float)pow2_height)); } else { texture->baseTexture.pow2Matrix[0] = 1.0f; texture->baseTexture.pow2Matrix[5] = 1.0f; } texture->baseTexture.pow2Matrix[10] = 1.0f; texture->baseTexture.pow2Matrix[15] = 1.0f; texture->baseTexture.target = GL_TEXTURE_2D; texture->baseTexture.cond_np2 = FALSE; } TRACE("xf(%f) yf(%f)\n", texture->baseTexture.pow2Matrix[0], texture->baseTexture.pow2Matrix[5]); /* Generate all the surfaces. */ tmp_w = width; tmp_h = height; for (i = 0; i < texture->baseTexture.level_count; ++i) { IWineD3DSurface *surface; /* Use the callback to create the texture surface. */ hr = IWineD3DDeviceParent_CreateSurface(device->device_parent, parent, tmp_w, tmp_h, format->id, usage, pool, i, 0, &surface); if (FAILED(hr)) { FIXME("Failed to create surface %p, hr %#x\n", texture, hr); texture_cleanup(texture); return hr; } surface_set_container((IWineD3DSurfaceImpl *)surface, WINED3D_CONTAINER_TEXTURE, (IWineD3DBase *)texture); surface_set_texture_target((IWineD3DSurfaceImpl *)surface, texture->baseTexture.target); texture->baseTexture.sub_resources[i] = &((IWineD3DSurfaceImpl *)surface)->resource; TRACE("Created surface level %u @ %p.\n", i, surface); /* Calculate the next mipmap level. */ tmp_w = max(1, tmp_w >> 1); tmp_h = max(1, tmp_h >> 1); } return WINED3D_OK; }
HRESULT volumetexture_init(IWineD3DBaseTextureImpl *texture, UINT width, UINT height, UINT depth, UINT levels, IWineD3DDeviceImpl *device, DWORD usage, enum wined3d_format_id format_id, WINED3DPOOL pool, void *parent, const struct wined3d_parent_ops *parent_ops) { const struct wined3d_gl_info *gl_info = &device->adapter->gl_info; const struct wined3d_format *format = wined3d_get_format(gl_info, format_id); UINT tmp_w, tmp_h, tmp_d; unsigned int i; HRESULT hr; /* TODO: It should only be possible to create textures for formats * that are reported as supported. */ if (WINED3DFMT_UNKNOWN >= format_id) { WARN("(%p) : Texture cannot be created with a format of WINED3DFMT_UNKNOWN.\n", texture); return WINED3DERR_INVALIDCALL; } if (!gl_info->supported[EXT_TEXTURE3D]) { WARN("(%p) : Texture cannot be created - no volume texture support.\n", texture); return WINED3DERR_INVALIDCALL; } /* Calculate levels for mip mapping. */ if (usage & WINED3DUSAGE_AUTOGENMIPMAP) { if (!gl_info->supported[SGIS_GENERATE_MIPMAP]) { WARN("No mipmap generation support, returning D3DERR_INVALIDCALL.\n"); return WINED3DERR_INVALIDCALL; } if (levels > 1) { WARN("D3DUSAGE_AUTOGENMIPMAP is set, and level count > 1, returning D3DERR_INVALIDCALL.\n"); return WINED3DERR_INVALIDCALL; } levels = 1; } else if (!levels) { levels = wined3d_log2i(max(max(width, height), depth)) + 1; TRACE("Calculated levels = %u.\n", levels); } texture->lpVtbl = &IWineD3DVolumeTexture_Vtbl; hr = basetexture_init((IWineD3DBaseTextureImpl *)texture, &volumetexture_ops, 1, levels, WINED3DRTYPE_VOLUMETEXTURE, device, usage, format, pool, parent, parent_ops, &volumetexture_resource_ops); if (FAILED(hr)) { WARN("Failed to initialize basetexture, returning %#x.\n", hr); return hr; } /* Is NP2 support for volumes needed? */ texture->baseTexture.pow2Matrix[0] = 1.0f; texture->baseTexture.pow2Matrix[5] = 1.0f; texture->baseTexture.pow2Matrix[10] = 1.0f; texture->baseTexture.pow2Matrix[15] = 1.0f; texture->baseTexture.target = GL_TEXTURE_3D; /* Generate all the surfaces. */ tmp_w = width; tmp_h = height; tmp_d = depth; for (i = 0; i < texture->baseTexture.level_count; ++i) { IWineD3DVolume *volume; /* Create the volume. */ hr = IWineD3DDeviceParent_CreateVolume(device->device_parent, parent, tmp_w, tmp_h, tmp_d, format_id, pool, usage, &volume); if (FAILED(hr)) { ERR("Creating a volume for the volume texture failed, hr %#x.\n", hr); volumetexture_cleanup(texture); return hr; } /* Set its container to this texture. */ volume_set_container((IWineD3DVolumeImpl *)volume, texture); texture->baseTexture.sub_resources[i] = &((IWineD3DVolumeImpl *)volume)->resource; /* Calculate the next mipmap level. */ tmp_w = max(1, tmp_w >> 1); tmp_h = max(1, tmp_h >> 1); tmp_d = max(1, tmp_d >> 1); } return WINED3D_OK; }
static HRESULT cubetexture_init(struct wined3d_texture *texture, UINT edge_length, UINT levels, struct wined3d_device *device, DWORD usage, enum wined3d_format_id format_id, enum wined3d_pool pool, void *parent, const struct wined3d_parent_ops *parent_ops) { const struct wined3d_gl_info *gl_info = &device->adapter->gl_info; const struct wined3d_format *format = wined3d_get_format(gl_info, format_id); UINT pow2_edge_length; unsigned int i, j; UINT tmp_w; HRESULT hr; /* TODO: It should only be possible to create textures for formats * that are reported as supported. */ if (WINED3DFMT_UNKNOWN >= format_id) { WARN("(%p) : Texture cannot be created with a format of WINED3DFMT_UNKNOWN.\n", texture); return WINED3DERR_INVALIDCALL; } if (!gl_info->supported[ARB_TEXTURE_CUBE_MAP] && pool != WINED3D_POOL_SCRATCH) { WARN("(%p) : Tried to create not supported cube texture.\n", texture); return WINED3DERR_INVALIDCALL; } /* Calculate levels for mip mapping */ if (usage & WINED3DUSAGE_AUTOGENMIPMAP) { if (!gl_info->supported[SGIS_GENERATE_MIPMAP]) { WARN("No mipmap generation support, returning D3DERR_INVALIDCALL.\n"); return WINED3DERR_INVALIDCALL; } if (levels > 1) { WARN("D3DUSAGE_AUTOGENMIPMAP is set, and level count > 1, returning D3DERR_INVALIDCALL.\n"); return WINED3DERR_INVALIDCALL; } levels = 1; } else if (!levels) { levels = wined3d_log2i(edge_length) + 1; TRACE("Calculated levels = %u.\n", levels); } hr = wined3d_texture_init(texture, &texture2d_ops, 6, levels, WINED3D_RTYPE_CUBE_TEXTURE, device, usage, format, pool, parent, parent_ops, &texture2d_resource_ops); if (FAILED(hr)) { WARN("Failed to initialize texture, returning %#x\n", hr); return hr; } /* Find the nearest pow2 match. */ pow2_edge_length = 1; while (pow2_edge_length < edge_length) pow2_edge_length <<= 1; if (gl_info->supported[ARB_TEXTURE_NON_POWER_OF_TWO] || (edge_length == pow2_edge_length)) { /* Precalculated scaling for 'faked' non power of two texture coords. */ texture->pow2_matrix[0] = 1.0f; texture->pow2_matrix[5] = 1.0f; texture->pow2_matrix[10] = 1.0f; texture->pow2_matrix[15] = 1.0f; } else { /* Precalculated scaling for 'faked' non power of two texture coords. */ texture->pow2_matrix[0] = ((float)edge_length) / ((float)pow2_edge_length); texture->pow2_matrix[5] = ((float)edge_length) / ((float)pow2_edge_length); texture->pow2_matrix[10] = ((float)edge_length) / ((float)pow2_edge_length); texture->pow2_matrix[15] = 1.0f; texture->flags &= ~WINED3D_TEXTURE_POW2_MAT_IDENT; } texture->target = GL_TEXTURE_CUBE_MAP_ARB; /* Generate all the surfaces. */ tmp_w = edge_length; for (i = 0; i < texture->level_count; ++i) { /* Create the 6 faces. */ for (j = 0; j < 6; ++j) { static const GLenum cube_targets[6] = { GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB, GL_TEXTURE_CUBE_MAP_NEGATIVE_X_ARB, GL_TEXTURE_CUBE_MAP_POSITIVE_Y_ARB, GL_TEXTURE_CUBE_MAP_NEGATIVE_Y_ARB, GL_TEXTURE_CUBE_MAP_POSITIVE_Z_ARB, GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB, }; UINT idx = j * texture->level_count + i; struct wined3d_surface *surface; if (FAILED(hr = device->device_parent->ops->create_texture_surface(device->device_parent, parent, tmp_w, tmp_w, format_id, usage, pool, idx, &surface))) { FIXME("(%p) Failed to create surface, hr %#x.\n", texture, hr); wined3d_texture_cleanup(texture); return hr; } surface_set_container(surface, WINED3D_CONTAINER_TEXTURE, texture); surface_set_texture_target(surface, cube_targets[j], i); texture->sub_resources[idx] = &surface->resource; TRACE("Created surface level %u @ %p.\n", i, surface); } tmp_w = max(1, tmp_w >> 1); } return WINED3D_OK; }
static HRESULT texture_init(struct wined3d_texture *texture, const struct wined3d_resource_desc *desc, UINT levels, DWORD surface_flags, struct wined3d_device *device, void *parent, const struct wined3d_parent_ops *parent_ops) { const struct wined3d_gl_info *gl_info = &device->adapter->gl_info; struct wined3d_resource_desc surface_desc; UINT pow2_width, pow2_height; unsigned int i; HRESULT hr; /* TODO: It should only be possible to create textures for formats * that are reported as supported. */ if (WINED3DFMT_UNKNOWN >= desc->format) { WARN("(%p) : Texture cannot be created with a format of WINED3DFMT_UNKNOWN.\n", texture); return WINED3DERR_INVALIDCALL; } /* Non-power2 support. */ if (gl_info->supported[ARB_TEXTURE_NON_POWER_OF_TWO]) { pow2_width = desc->width; pow2_height = desc->height; } else { /* Find the nearest pow2 match. */ pow2_width = pow2_height = 1; while (pow2_width < desc->width) pow2_width <<= 1; while (pow2_height < desc->height) pow2_height <<= 1; if (pow2_width != desc->width || pow2_height != desc->height) { /* levels == 0 returns an error as well */ if (levels != 1) { if (desc->pool == WINED3D_POOL_SCRATCH) { WARN("Creating a scratch mipmapped NPOT texture despite lack of HW support.\n"); } else { WARN("Attempted to create a mipmapped NPOT texture without unconditional NPOT support.\n"); return WINED3DERR_INVALIDCALL; } } } } /* Calculate levels for mip mapping. */ if (desc->usage & WINED3DUSAGE_AUTOGENMIPMAP) { if (!gl_info->supported[SGIS_GENERATE_MIPMAP]) { WARN("No mipmap generation support, returning WINED3DERR_INVALIDCALL.\n"); return WINED3DERR_INVALIDCALL; } if (levels > 1) { WARN("D3DUSAGE_AUTOGENMIPMAP is set, and level count > 1, returning WINED3DERR_INVALIDCALL.\n"); return WINED3DERR_INVALIDCALL; } levels = 1; } else if (!levels) { levels = wined3d_log2i(max(desc->width, desc->height)) + 1; TRACE("Calculated levels = %u.\n", levels); } if (FAILED(hr = wined3d_texture_init(texture, &texture2d_ops, 1, levels, desc, 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_info->supported[WINED3D_GL_NORMALIZED_TEXRECT] && (desc->width != pow2_width || desc->height != pow2_height)) { texture->pow2_matrix[0] = 1.0f; texture->pow2_matrix[5] = 1.0f; texture->pow2_matrix[10] = 1.0f; texture->pow2_matrix[15] = 1.0f; texture->target = GL_TEXTURE_2D; texture->flags |= WINED3D_TEXTURE_COND_NP2; texture->min_mip_lookup = minMipLookup_noFilter; } else if (gl_info->supported[ARB_TEXTURE_RECTANGLE] && (desc->width != pow2_width || desc->height != pow2_height)) { texture->pow2_matrix[0] = (float)desc->width; texture->pow2_matrix[5] = (float)desc->height; texture->pow2_matrix[10] = 1.0f; texture->pow2_matrix[15] = 1.0f; texture->target = GL_TEXTURE_RECTANGLE_ARB; texture->flags |= WINED3D_TEXTURE_COND_NP2; texture->flags &= ~WINED3D_TEXTURE_POW2_MAT_IDENT; if (texture->resource.format->flags & WINED3DFMT_FLAG_FILTERING) texture->min_mip_lookup = minMipLookup_noMip; else texture->min_mip_lookup = minMipLookup_noFilter; } else { if ((desc->width != pow2_width) || (desc->height != pow2_height)) { texture->pow2_matrix[0] = (((float)desc->width) / ((float)pow2_width)); texture->pow2_matrix[5] = (((float)desc->height) / ((float)pow2_height)); texture->flags &= ~WINED3D_TEXTURE_POW2_MAT_IDENT; } else { texture->pow2_matrix[0] = 1.0f; texture->pow2_matrix[5] = 1.0f; } texture->pow2_matrix[10] = 1.0f; texture->pow2_matrix[15] = 1.0f; texture->target = GL_TEXTURE_2D; } TRACE("xf(%f) yf(%f)\n", texture->pow2_matrix[0], texture->pow2_matrix[5]); /* Generate all the surfaces. */ surface_desc = *desc; surface_desc.resource_type = WINED3D_RTYPE_SURFACE; for (i = 0; i < texture->level_count; ++i) { struct wined3d_surface *surface; if (FAILED(hr = wined3d_surface_create(texture, &surface_desc, texture->target, i, 0, surface_flags, &surface))) { WARN("Failed to create surface, hr %#x.\n", hr); wined3d_texture_cleanup(texture); return hr; } texture->sub_resources[i] = &surface->resource; TRACE("Created surface level %u @ %p.\n", i, surface); /* Calculate the next mipmap level. */ surface_desc.width = max(1, surface_desc.width >> 1); surface_desc.height = max(1, surface_desc.height >> 1); } return WINED3D_OK; }
static HRESULT cubetexture_init(struct wined3d_texture *texture, const struct wined3d_resource_desc *desc, UINT levels, DWORD surface_flags, struct wined3d_device *device, void *parent, const struct wined3d_parent_ops *parent_ops) { const struct wined3d_gl_info *gl_info = &device->adapter->gl_info; struct wined3d_resource_desc surface_desc; unsigned int i, j; HRESULT hr; /* TODO: It should only be possible to create textures for formats * that are reported as supported. */ if (WINED3DFMT_UNKNOWN >= desc->format) { WARN("(%p) : Texture cannot be created with a format of WINED3DFMT_UNKNOWN.\n", texture); return WINED3DERR_INVALIDCALL; } if (!gl_info->supported[ARB_TEXTURE_CUBE_MAP] && desc->pool != WINED3D_POOL_SCRATCH) { WARN("(%p) : Tried to create not supported cube texture.\n", texture); return WINED3DERR_INVALIDCALL; } /* Calculate levels for mip mapping */ if (desc->usage & WINED3DUSAGE_AUTOGENMIPMAP) { if (!gl_info->supported[SGIS_GENERATE_MIPMAP]) { WARN("No mipmap generation support, returning D3DERR_INVALIDCALL.\n"); return WINED3DERR_INVALIDCALL; } if (levels > 1) { WARN("D3DUSAGE_AUTOGENMIPMAP is set, and level count > 1, returning D3DERR_INVALIDCALL.\n"); return WINED3DERR_INVALIDCALL; } levels = 1; } else if (!levels) { levels = wined3d_log2i(desc->width) + 1; TRACE("Calculated levels = %u.\n", levels); } if (!gl_info->supported[ARB_TEXTURE_NON_POWER_OF_TWO]) { UINT pow2_edge_length = 1; while (pow2_edge_length < desc->width) pow2_edge_length <<= 1; if (desc->width != pow2_edge_length) { if (desc->pool == WINED3D_POOL_SCRATCH) { /* SCRATCH textures cannot be used for texturing */ WARN("Creating a scratch NPOT cube texture despite lack of HW support.\n"); } else { WARN("Attempted to create a NPOT cube texture (edge length %u) without GL support.\n", desc->width); return WINED3DERR_INVALIDCALL; } } } if (FAILED(hr = wined3d_texture_init(texture, &texture2d_ops, 6, levels, desc, device, parent, parent_ops, &texture_resource_ops))) { WARN("Failed to initialize texture, returning %#x\n", hr); return hr; } texture->pow2_matrix[0] = 1.0f; texture->pow2_matrix[5] = 1.0f; texture->pow2_matrix[10] = 1.0f; texture->pow2_matrix[15] = 1.0f; texture->target = GL_TEXTURE_CUBE_MAP_ARB; /* Generate all the surfaces. */ surface_desc = *desc; surface_desc.resource_type = WINED3D_RTYPE_SURFACE; for (i = 0; i < texture->level_count; ++i) { /* Create the 6 faces. */ for (j = 0; j < 6; ++j) { static const GLenum cube_targets[6] = { GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB, GL_TEXTURE_CUBE_MAP_NEGATIVE_X_ARB, GL_TEXTURE_CUBE_MAP_POSITIVE_Y_ARB, GL_TEXTURE_CUBE_MAP_NEGATIVE_Y_ARB, GL_TEXTURE_CUBE_MAP_POSITIVE_Z_ARB, GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB, }; UINT idx = j * texture->level_count + i; struct wined3d_surface *surface; if (FAILED(hr = wined3d_surface_create(texture, &surface_desc, cube_targets[j], i, j, surface_flags, &surface))) { WARN("Failed to create surface, hr %#x.\n", hr); wined3d_texture_cleanup(texture); return hr; } texture->sub_resources[idx] = &surface->resource; TRACE("Created surface level %u @ %p.\n", i, surface); } surface_desc.width = max(1, surface_desc.width >> 1); surface_desc.height = surface_desc.width; } return WINED3D_OK; }
static HRESULT volumetexture_init(struct wined3d_texture *texture, const struct wined3d_resource_desc *desc, UINT levels, struct wined3d_device *device, void *parent, const struct wined3d_parent_ops *parent_ops) { const struct wined3d_gl_info *gl_info = &device->adapter->gl_info; struct wined3d_resource_desc volume_desc; unsigned int i; HRESULT hr; /* TODO: It should only be possible to create textures for formats * that are reported as supported. */ if (WINED3DFMT_UNKNOWN >= desc->format) { WARN("(%p) : Texture cannot be created with a format of WINED3DFMT_UNKNOWN.\n", texture); return WINED3DERR_INVALIDCALL; } if (!gl_info->supported[EXT_TEXTURE3D]) { WARN("(%p) : Texture cannot be created - no volume texture support.\n", texture); return WINED3DERR_INVALIDCALL; } /* Calculate levels for mip mapping. */ if (desc->usage & WINED3DUSAGE_AUTOGENMIPMAP) { if (!gl_info->supported[SGIS_GENERATE_MIPMAP]) { WARN("No mipmap generation support, returning D3DERR_INVALIDCALL.\n"); return WINED3DERR_INVALIDCALL; } if (levels > 1) { WARN("D3DUSAGE_AUTOGENMIPMAP is set, and level count > 1, returning D3DERR_INVALIDCALL.\n"); return WINED3DERR_INVALIDCALL; } levels = 1; } else if (!levels) { levels = wined3d_log2i(max(max(desc->width, desc->height), desc->depth)) + 1; TRACE("Calculated levels = %u.\n", levels); } if (!gl_info->supported[ARB_TEXTURE_NON_POWER_OF_TWO]) { UINT pow2_w, pow2_h, pow2_d; pow2_w = 1; while (pow2_w < desc->width) pow2_w <<= 1; pow2_h = 1; while (pow2_h < desc->height) pow2_h <<= 1; pow2_d = 1; while (pow2_d < desc->depth) pow2_d <<= 1; if (pow2_w != desc->width || pow2_h != desc->height || pow2_d != desc->depth) { if (desc->pool == WINED3D_POOL_SCRATCH) { WARN("Creating a scratch NPOT volume texture despite lack of HW support.\n"); } else { WARN("Attempted to create a NPOT volume texture (%u, %u, %u) without GL support.\n", desc->width, desc->height, desc->depth); return WINED3DERR_INVALIDCALL; } } } if (FAILED(hr = wined3d_texture_init(texture, &texture3d_ops, 1, levels, desc, device, parent, parent_ops, &texture_resource_ops))) { WARN("Failed to initialize texture, returning %#x.\n", hr); return hr; } texture->pow2_matrix[0] = 1.0f; texture->pow2_matrix[5] = 1.0f; texture->pow2_matrix[10] = 1.0f; texture->pow2_matrix[15] = 1.0f; texture->target = GL_TEXTURE_3D; /* Generate all the surfaces. */ volume_desc = *desc; volume_desc.resource_type = WINED3D_RTYPE_VOLUME; for (i = 0; i < texture->level_count; ++i) { struct wined3d_volume *volume; if (FAILED(hr = wined3d_volume_create(texture, &volume_desc, i, &volume))) { ERR("Creating a volume for the volume texture failed, hr %#x.\n", hr); wined3d_texture_cleanup(texture); return hr; } texture->sub_resources[i] = &volume->resource; /* Calculate the next mipmap level. */ volume_desc.width = max(1, volume_desc.width >> 1); volume_desc.height = max(1, volume_desc.height >> 1); volume_desc.depth = max(1, volume_desc.depth >> 1); } return WINED3D_OK; }
HRESULT texture_init(IWineD3DTextureImpl *texture, UINT width, UINT height, UINT levels, IWineD3DDeviceImpl *device, DWORD usage, WINED3DFORMAT format, WINED3DPOOL pool, IUnknown *parent, const struct wined3d_parent_ops *parent_ops #ifdef VBOX_WITH_WDDM , HANDLE *shared_handle , void **pavClientMem #endif ) { const struct wined3d_gl_info *gl_info = &device->adapter->gl_info; const struct wined3d_format_desc *format_desc = getFormatDescEntry(format, gl_info); UINT pow2_width, pow2_height; UINT tmp_w, tmp_h; unsigned int i; HRESULT hr; /* TODO: It should only be possible to create textures for formats * that are reported as supported. */ if (WINED3DFMT_UNKNOWN >= format) { WARN("(%p) : Texture cannot be created with a format of WINED3DFMT_UNKNOWN.\n", texture); return WINED3DERR_INVALIDCALL; } /* Non-power2 support. */ if (gl_info->supported[ARB_TEXTURE_NON_POWER_OF_TWO]) { pow2_width = width; pow2_height = height; } else { /* Find the nearest pow2 match. */ pow2_width = pow2_height = 1; while (pow2_width < width) pow2_width <<= 1; while (pow2_height < height) pow2_height <<= 1; if (pow2_width != width || pow2_height != height) { if (levels > 1) { WARN("Attempted to create a mipmapped np2 texture without unconditional np2 support.\n"); return WINED3DERR_INVALIDCALL; } levels = 1; } } /* Calculate levels for mip mapping. */ if (usage & WINED3DUSAGE_AUTOGENMIPMAP) { if (!gl_info->supported[SGIS_GENERATE_MIPMAP]) { WARN("No mipmap generation support, returning WINED3DERR_INVALIDCALL.\n"); return WINED3DERR_INVALIDCALL; } if (levels > 1) { WARN("D3DUSAGE_AUTOGENMIPMAP is set, and level count > 1, returning WINED3DERR_INVALIDCALL.\n"); return WINED3DERR_INVALIDCALL; } levels = 1; } else if (!levels) { levels = wined3d_log2i(max(width, height)) + 1; TRACE("Calculated levels = %u.\n", levels); } texture->lpVtbl = &IWineD3DTexture_Vtbl; hr = basetexture_init((IWineD3DBaseTextureImpl *)texture, levels, WINED3DRTYPE_TEXTURE, device, 0, usage, format_desc, pool, parent, parent_ops #ifdef VBOX_WITH_WDDM , shared_handle, pavClientMem #endif ); if (FAILED(hr)) { WARN("Failed to initialize basetexture, returning %#x.\n", hr); return hr; } /* Precalculated scaling for 'faked' non power of two texture coords. * Second also don't use ARB_TEXTURE_RECTANGLE in case the surface format is P8 and EXT_PALETTED_TEXTURE * is used in combination with texture uploads (RTL_READTEX). The reason is that EXT_PALETTED_TEXTURE * doesn't work in combination with ARB_TEXTURE_RECTANGLE. */ if (gl_info->supported[WINE_NORMALIZED_TEXRECT] && (width != pow2_width || height != pow2_height)) { texture->baseTexture.pow2Matrix[0] = 1.0f; texture->baseTexture.pow2Matrix[5] = 1.0f; texture->baseTexture.pow2Matrix[10] = 1.0f; texture->baseTexture.pow2Matrix[15] = 1.0f; texture->target = GL_TEXTURE_2D; texture->cond_np2 = TRUE; texture->baseTexture.minMipLookup = minMipLookup_noFilter; } else if (gl_info->supported[ARB_TEXTURE_RECTANGLE] && (width != pow2_width || height != pow2_height) && !(format_desc->format == WINED3DFMT_P8_UINT && gl_info->supported[EXT_PALETTED_TEXTURE] && wined3d_settings.rendertargetlock_mode == RTL_READTEX)) { if ((width != 1) || (height != 1)) texture->baseTexture.pow2Matrix_identity = FALSE; texture->baseTexture.pow2Matrix[0] = (float)width; texture->baseTexture.pow2Matrix[5] = (float)height; texture->baseTexture.pow2Matrix[10] = 1.0f; texture->baseTexture.pow2Matrix[15] = 1.0f; texture->target = GL_TEXTURE_RECTANGLE_ARB; texture->cond_np2 = TRUE; if(texture->resource.format_desc->Flags & WINED3DFMT_FLAG_FILTERING) { texture->baseTexture.minMipLookup = minMipLookup_noMip; } else { texture->baseTexture.minMipLookup = minMipLookup_noFilter; } } else { if ((width != pow2_width) || (height != pow2_height)) { texture->baseTexture.pow2Matrix_identity = FALSE; texture->baseTexture.pow2Matrix[0] = (((float)width) / ((float)pow2_width)); texture->baseTexture.pow2Matrix[5] = (((float)height) / ((float)pow2_height)); } else { texture->baseTexture.pow2Matrix[0] = 1.0f; texture->baseTexture.pow2Matrix[5] = 1.0f; } texture->baseTexture.pow2Matrix[10] = 1.0f; texture->baseTexture.pow2Matrix[15] = 1.0f; texture->target = GL_TEXTURE_2D; texture->cond_np2 = FALSE; } TRACE("xf(%f) yf(%f)\n", texture->baseTexture.pow2Matrix[0], texture->baseTexture.pow2Matrix[5]); /* Generate all the surfaces. */ tmp_w = width; tmp_h = height; for (i = 0; i < texture->baseTexture.levels; ++i) { #ifdef VBOX_WITH_WDDM /* Use the callback to create the texture surface. */ hr = IWineD3DDeviceParent_CreateSurface(device->device_parent, parent, tmp_w, tmp_h, format_desc->format, usage, pool, i, WINED3DCUBEMAP_FACE_POSITIVE_X, &texture->surfaces[i] , NULL /* <- we first create a surface in an everage "non-shared" fashion and initialize its share properties later (see below) * this is done this way because the surface does not have its parent (texture) setup properly * thus we can not initialize texture at this stage */ , pavClientMem ? pavClientMem[i] : NULL); #else /* Use the callback to create the texture surface. */ hr = IWineD3DDeviceParent_CreateSurface(device->device_parent, parent, tmp_w, tmp_h, format_desc->format, usage, pool, i, WINED3DCUBEMAP_FACE_POSITIVE_X, &texture->surfaces[i]); #endif if (FAILED(hr)) { FIXME("Failed to create surface %p, hr %#x\n", texture, hr); texture->surfaces[i] = NULL; texture_cleanup(texture); return hr; } IWineD3DSurface_SetContainer(texture->surfaces[i], (IWineD3DBase *)texture); TRACE("Created surface level %u @ %p.\n", i, texture->surfaces[i]); surface_set_texture_target(texture->surfaces[i], texture->target); /* Calculate the next mipmap level. */ tmp_w = max(1, tmp_w >> 1); tmp_h = max(1, tmp_h >> 1); } texture->baseTexture.internal_preload = texture_internal_preload; #ifdef VBOX_WITH_WDDM if (VBOXSHRC_IS_SHARED(texture)) { Assert(shared_handle); for (i = 0; i < texture->baseTexture.levels; ++i) { VBOXSHRC_COPY_SHAREDATA((IWineD3DSurfaceImpl*)texture->surfaces[i], texture); } #ifdef DEBUG for (i = 0; i < texture->baseTexture.levels; ++i) { Assert(!((IWineD3DSurfaceImpl*)texture->surfaces[i])->texture_name); } #endif for (i = 0; i < texture->baseTexture.levels; ++i) { if (!VBOXSHRC_IS_SHARED_OPENED(texture)) { IWineD3DSurface_LoadLocation(texture->surfaces[i], SFLAG_INTEXTURE, NULL); Assert(!(*shared_handle)); *shared_handle = VBOXSHRC_GET_SHAREHANDLE(texture); } else { surface_setup_location_onopen((IWineD3DSurfaceImpl*)texture->surfaces[i]); Assert(*shared_handle); Assert(*shared_handle == VBOXSHRC_GET_SHAREHANDLE(texture)); } } #ifdef DEBUG for (i = 0; i < texture->baseTexture.levels; ++i) { Assert((GLuint)(*shared_handle) == ((IWineD3DSurfaceImpl*)texture->surfaces[i])->texture_name); } #endif if (!VBOXSHRC_IS_SHARED_OPENED(texture)) { struct wined3d_context * context; Assert(!device->isInDraw); /* flush to ensure the texture is allocated before it is used by another * process opening it */ context = context_acquire(device, NULL, CTXUSAGE_RESOURCELOAD); if (context->valid) { wglFlush(); } else { ERR("invalid context!"); } context_release(context); } } else { Assert(!shared_handle); } #endif return WINED3D_OK; }