diff --git a/dlls/ddraw/tests/ddraw7.c b/dlls/ddraw/tests/ddraw7.c index 53e47250e3d..c85f0201118 100644 --- a/dlls/ddraw/tests/ddraw7.c +++ b/dlls/ddraw/tests/ddraw7.c @@ -7126,6 +7126,64 @@ static void test_set_surface_desc(void) IDirectDrawSurface7_Release(surface); + /* Test mipmap texture. */ + reset_ddsd(&ddsd); + ddsd.dwFlags = DDSD_WIDTH | DDSD_HEIGHT | DDSD_CAPS | DDSD_MIPMAPCOUNT; + ddsd.dwWidth = 8; + ddsd.dwHeight = 8; + U2(ddsd).dwMipMapCount = 3; + ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE | DDSCAPS_VIDEOMEMORY | DDSCAPS_COMPLEX | DDSCAPS_MIPMAP; + + hr = IDirectDraw7_CreateSurface(ddraw, &ddsd, &surface, NULL); + ok(hr == DD_OK || hr == DDERR_NODIRECTDRAWHW || hr == E_NOINTERFACE, "Got unexpected hr %#x.\n", hr); + + if (FAILED(hr)) + { + skip("Mipmaps are not supported.\n"); + } + else + { + /* Changing surface desc for mipmap fails even without changing any + * parameters. */ + hr = IDirectDrawSurface7_SetSurfaceDesc(surface, &ddsd, 0); + ok(hr == DDERR_INVALIDSURFACETYPE, "Got unexpected hr %#x.\n", hr); + IDirectDrawSurface7_Release(surface); + } + + /* Test surface created with DDSD_LPSURFACE. */ + reset_ddsd(&ddsd); + ddsd.dwFlags = DDSD_WIDTH | DDSD_HEIGHT | DDSD_CAPS | DDSD_LPSURFACE | DDSD_PITCH; + ddsd.dwWidth = 8; + ddsd.dwHeight = 8; + ddsd.lpSurface = data; + U1(ddsd).lPitch = 8 * 4; + ddsd.ddsCaps.dwCaps = DDSCAPS_SYSTEMMEMORY | DDSCAPS_OFFSCREENPLAIN; + hr = IDirectDraw7_CreateSurface(ddraw, &ddsd, &surface, NULL); + ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr); + + hr = IDirectDrawSurface7_SetSurfaceDesc(surface, &ddsd, 0); + ok(hr == DDERR_INVALIDCAPS, "Got unexpected hr %#x.\n", hr); + + reset_ddsd(&ddsd); + ddsd.dwFlags = DDSD_WIDTH | DDSD_HEIGHT; + ddsd.dwWidth = 8; + ddsd.dwHeight = 8; + /* Cannot reset lpSurface. */ + hr = IDirectDrawSurface7_SetSurfaceDesc(surface, &ddsd, 0); + ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr); + + reset_ddsd(&ddsd); + ddsd.dwFlags = DDSD_WIDTH | DDSD_HEIGHT | DDSD_LPSURFACE | DDSD_PITCH; + ddsd.dwWidth = 4; + ddsd.dwHeight = 4; + ddsd.lpSurface = data; + U1(ddsd).lPitch = 8 * 4; + /* Can change the parameters of surface created with DDSD_LPSURFACE. */ + hr = IDirectDrawSurface7_SetSurfaceDesc(surface, &ddsd, 0); + ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr); + + IDirectDrawSurface7_Release(surface); + /* SetSurfaceDesc needs systemmemory surfaces. * * As a sidenote, fourcc surfaces aren't allowed in sysmem, thus testing @@ -13347,14 +13405,14 @@ static void test_display_mode_surface_pixel_format(void) surface_desc.dwSize = sizeof(surface_desc); hr = IDirectDraw7_GetDisplayMode(ddraw, &surface_desc); - ok(SUCCEEDED(hr), "Failed to get display mode, hr %#x.\n", hr); + ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr); width = surface_desc.dwWidth; height = surface_desc.dwHeight; window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW, 0, 0, width, height, NULL, NULL, NULL, NULL); hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN); - ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr); + ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr); bpp = 0; if (SUCCEEDED(IDirectDraw7_SetDisplayMode(ddraw, width, height, 16, 0, 0))) @@ -13367,7 +13425,7 @@ static void test_display_mode_surface_pixel_format(void) surface_desc.dwSize = sizeof(surface_desc); hr = IDirectDraw7_GetDisplayMode(ddraw, &surface_desc); - ok(SUCCEEDED(hr), "Failed to get display mode, hr %#x.\n", hr); + ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr); ok(surface_desc.dwWidth == width, "Got width %u, expected %u.\n", surface_desc.dwWidth, width); ok(surface_desc.dwHeight == height, "Got height %u, expected %u.\n", surface_desc.dwHeight, height); ok(U1(U4(surface_desc).ddpfPixelFormat).dwRGBBitCount == bpp, "Got bpp %u, expected %u.\n", @@ -13379,9 +13437,9 @@ static void test_display_mode_surface_pixel_format(void) U5(surface_desc).dwBackBufferCount = 1; surface_desc.ddsCaps.dwCaps = DDSCAPS_COMPLEX | DDSCAPS_FLIP | DDSCAPS_PRIMARYSURFACE; hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &surface, NULL); - ok(hr == D3D_OK, "Failed to create surface, hr %#x.\n", hr); + ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr); hr = IDirectDrawSurface7_GetSurfaceDesc(surface, &surface_desc); - ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr); + ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr); ok(surface_desc.dwWidth == width, "Got width %u, expected %u.\n", surface_desc.dwWidth, width); ok(surface_desc.dwHeight == height, "Got height %u, expected %u.\n", surface_desc.dwHeight, height); ok(U4(surface_desc).ddpfPixelFormat.dwFlags == DDPF_RGB, "Got unexpected pixel format flags %#x.\n", @@ -13397,15 +13455,39 @@ static void test_display_mode_surface_pixel_format(void) surface_desc.dwHeight = height; surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN; hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &surface, NULL); - ok(hr == D3D_OK, "Failed to create surface, hr %#x.\n", hr); + ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr); hr = IDirectDrawSurface7_GetSurfaceDesc(surface, &surface_desc); - ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr); + ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr); ok(U4(surface_desc).ddpfPixelFormat.dwFlags == DDPF_RGB, "Got unexpected pixel format flags %#x.\n", U4(surface_desc).ddpfPixelFormat.dwFlags); ok(U1(U4(surface_desc).ddpfPixelFormat).dwRGBBitCount == bpp, "Got bpp %u, expected %u.\n", U1(U4(surface_desc).ddpfPixelFormat).dwRGBBitCount, bpp); IDirectDrawSurface7_Release(surface); + /* Test compatibility mode mipmap texture creation. */ + hr = IDirectDraw7_SetDisplayMode(ddraw, width, height, 16, 0, 0); + ok(hr == DD_OK || hr == E_NOTIMPL, "Got unexpected hr %#x.\n", hr); + if (FAILED(hr)) + { + win_skip("SetDisplayMode failed, skipping test."); + goto done; + } + bpp = 16; + + memset(&surface_desc, 0, sizeof(surface_desc)); + surface_desc.dwSize = sizeof(surface_desc); + surface_desc.dwFlags = DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH | DDSD_MIPMAPCOUNT | DDSD_PITCH; + U2(surface_desc).dwMipMapCount = 2; + surface_desc.dwWidth = 4; + surface_desc.dwHeight = 4; + U1(surface_desc).lPitch = surface_desc.dwWidth * bpp / 8; + surface_desc.ddsCaps.dwCaps = DDSCAPS_TEXTURE | DDSCAPS_COMPLEX | DDSCAPS_MIPMAP | DDSCAPS_VIDEOMEMORY; + hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &surface, NULL); + ok(hr == DD_OK || hr == DDERR_NODIRECTDRAWHW, "Got unexpected hr %#x.\n", hr); + if (surface) + IDirectDrawSurface7_Release(surface); + +done: refcount = IDirectDraw7_Release(ddraw); ok(!refcount, "DirectDraw has %u references left.\n", refcount); DestroyWindow(window); diff --git a/dlls/wined3d/texture.c b/dlls/wined3d/texture.c index 49373eb58ac..de6999105d1 100644 --- a/dlls/wined3d/texture.c +++ b/dlls/wined3d/texture.c @@ -1748,11 +1748,13 @@ HRESULT CDECL wined3d_texture_update_desc(struct wined3d_texture *texture, UINT const struct wined3d_d3d_info *d3d_info; const struct wined3d_gl_info *gl_info; const struct wined3d_format *format; - const struct wined3d *d3d; struct wined3d_device *device; unsigned int resource_size; + const struct wined3d *d3d; + unsigned int slice_pitch; DWORD valid_location = 0; - BOOL create_dib = FALSE; + bool update_memory_only; + bool create_dib = false; TRACE("texture %p, width %u, height %u, format %s, multisample_type %#x, multisample_quality %u, " "mem %p, pitch %u.\n", @@ -1765,10 +1767,27 @@ HRESULT CDECL wined3d_texture_update_desc(struct wined3d_texture *texture, UINT format = wined3d_get_format(device->adapter, format_id, texture->resource.bind_flags); resource_size = wined3d_format_calculate_size(format, device->surface_alignment, width, height, 1); + update_memory_only = width == texture->resource.width && height == texture->resource.height + && format_id == texture->resource.format->id && multisample_type == texture->resource.multisample_type + && multisample_quality == texture->resource.multisample_quality; + + if (pitch) + slice_pitch = height * pitch; + else + wined3d_format_calculate_pitch(format, 1, width, height, &pitch, &slice_pitch); + + if (update_memory_only) + { + unsigned int current_row_pitch, current_slice_pitch; + + wined3d_texture_get_pitch(texture, 0, ¤t_row_pitch, ¤t_slice_pitch); + update_memory_only = pitch == current_row_pitch && slice_pitch == current_slice_pitch; + } + if (!resource_size) return WINED3DERR_INVALIDCALL; - if (texture->level_count * texture->layer_count > 1) + if (texture->level_count * texture->layer_count > 1 && !update_memory_only) { WARN("Texture has multiple sub-resources, not supported.\n"); return WINED3DERR_INVALIDCALL; @@ -1803,67 +1822,67 @@ HRESULT CDECL wined3d_texture_update_desc(struct wined3d_texture *texture, UINT wined3d_cs_emit_unload_resource(device->cs, &texture->resource); wined3d_resource_wait_idle(&texture->resource); - sub_resource = &texture->sub_resources[0]; if (texture->dc_info && texture->dc_info[0].dc) { struct wined3d_texture_idx texture_idx = {texture, 0}; wined3d_cs_destroy_object(device->cs, wined3d_texture_destroy_dc, &texture_idx); wined3d_cs_finish(device->cs, WINED3D_CS_QUEUE_DEFAULT); - create_dib = TRUE; + create_dib = true; } wined3d_resource_free_sysmem(&texture->resource); - if ((texture->row_pitch = pitch)) - texture->slice_pitch = height * pitch; - else - /* User memory surfaces don't have the regular surface alignment. */ - wined3d_format_calculate_pitch(format, 1, width, height, - &texture->row_pitch, &texture->slice_pitch); - - texture->resource.format = format; - texture->resource.multisample_type = multisample_type; - texture->resource.multisample_quality = multisample_quality; - texture->resource.width = width; - texture->resource.height = height; - if (!(texture->resource.access & WINED3D_RESOURCE_ACCESS_CPU) && d3d->flags & WINED3D_VIDMEM_ACCOUNTING) - adapter_adjust_memory(device->adapter, (INT64)texture->slice_pitch - texture->resource.size); - texture->resource.size = texture->slice_pitch; - sub_resource->size = texture->slice_pitch; - sub_resource->locations = WINED3D_LOCATION_DISCARDED; - - if (texture->texture_ops == &texture_gl_ops) + if (!update_memory_only) { - if (multisample_type && gl_info->supported[ARB_TEXTURE_MULTISAMPLE]) + sub_resource = &texture->sub_resources[0]; + + texture->row_pitch = pitch; + texture->slice_pitch = slice_pitch; + + texture->resource.format = format; + texture->resource.multisample_type = multisample_type; + texture->resource.multisample_quality = multisample_quality; + texture->resource.width = width; + texture->resource.height = height; + if (!(texture->resource.access & WINED3D_RESOURCE_ACCESS_CPU) && d3d->flags & WINED3D_VIDMEM_ACCOUNTING) + adapter_adjust_memory(device->adapter, (INT64)texture->slice_pitch - texture->resource.size); + texture->resource.size = texture->slice_pitch; + sub_resource->size = texture->slice_pitch; + sub_resource->locations = WINED3D_LOCATION_DISCARDED; + + if (texture->texture_ops == &texture_gl_ops) { - wined3d_texture_gl(texture)->target = GL_TEXTURE_2D_MULTISAMPLE; - texture->flags &= ~WINED3D_TEXTURE_DOWNLOADABLE; + if (multisample_type && gl_info->supported[ARB_TEXTURE_MULTISAMPLE]) + { + wined3d_texture_gl(texture)->target = GL_TEXTURE_2D_MULTISAMPLE; + texture->flags &= ~WINED3D_TEXTURE_DOWNLOADABLE; + } + else + { + wined3d_texture_gl(texture)->target = GL_TEXTURE_2D; + texture->flags |= WINED3D_TEXTURE_DOWNLOADABLE; + } + } + + if (((width & (width - 1)) || (height & (height - 1))) && !d3d_info->texture_npot + && !d3d_info->texture_npot_conditional) + { + texture->flags |= WINED3D_TEXTURE_COND_NP2_EMULATED; + texture->pow2_width = texture->pow2_height = 1; + while (texture->pow2_width < width) + texture->pow2_width <<= 1; + while (texture->pow2_height < height) + texture->pow2_height <<= 1; } else { - wined3d_texture_gl(texture)->target = GL_TEXTURE_2D; - texture->flags |= WINED3D_TEXTURE_DOWNLOADABLE; + texture->flags &= ~WINED3D_TEXTURE_COND_NP2_EMULATED; + texture->pow2_width = width; + texture->pow2_height = height; } } - if (((width & (width - 1)) || (height & (height - 1))) && !d3d_info->texture_npot - && !d3d_info->texture_npot_conditional) - { - texture->flags |= WINED3D_TEXTURE_COND_NP2_EMULATED; - texture->pow2_width = texture->pow2_height = 1; - while (texture->pow2_width < width) - texture->pow2_width <<= 1; - while (texture->pow2_height < height) - texture->pow2_height <<= 1; - } - else - { - texture->flags &= ~WINED3D_TEXTURE_COND_NP2_EMULATED; - texture->pow2_width = width; - texture->pow2_height = height; - } - if ((texture->user_memory = mem)) { texture->resource.map_binding = WINED3D_LOCATION_USER_MEMORY;