surface.c revision 02c9755012e37c41025d4bf7f11eb54f4c9618d6
f8a829bc862da0c232b1291990e1e2c990d40cf4vboxsync * IWineD3DSurface Implementation
f8a829bc862da0c232b1291990e1e2c990d40cf4vboxsync * Copyright 1998 Lionel Ulmer
f8a829bc862da0c232b1291990e1e2c990d40cf4vboxsync * Copyright 2000-2001 TransGaming Technologies Inc.
f8a829bc862da0c232b1291990e1e2c990d40cf4vboxsync * Copyright 2002-2005 Jason Edmeades
f8a829bc862da0c232b1291990e1e2c990d40cf4vboxsync * Copyright 2002-2003 Raphael Junqueira
f8a829bc862da0c232b1291990e1e2c990d40cf4vboxsync * Copyright 2004 Christian Costa
f8a829bc862da0c232b1291990e1e2c990d40cf4vboxsync * Copyright 2005 Oliver Stieber
f8a829bc862da0c232b1291990e1e2c990d40cf4vboxsync * Copyright 2006-2008 Stefan Dösinger for CodeWeavers
f8a829bc862da0c232b1291990e1e2c990d40cf4vboxsync * Copyright 2007-2008 Henri Verbeet
f8a829bc862da0c232b1291990e1e2c990d40cf4vboxsync * Copyright 2006-2008 Roderick Colenbrander
f8a829bc862da0c232b1291990e1e2c990d40cf4vboxsync * Copyright 2009 Henri Verbeet for CodeWeavers
f8a829bc862da0c232b1291990e1e2c990d40cf4vboxsync * This library is free software; you can redistribute it and/or
f8a829bc862da0c232b1291990e1e2c990d40cf4vboxsync * modify it under the terms of the GNU Lesser General Public
f8a829bc862da0c232b1291990e1e2c990d40cf4vboxsync * License as published by the Free Software Foundation; either
f8a829bc862da0c232b1291990e1e2c990d40cf4vboxsync * version 2.1 of the License, or (at your option) any later version.
f8a829bc862da0c232b1291990e1e2c990d40cf4vboxsync * This library is distributed in the hope that it will be useful,
f8a829bc862da0c232b1291990e1e2c990d40cf4vboxsync * but WITHOUT ANY WARRANTY; without even the implied warranty of
f8a829bc862da0c232b1291990e1e2c990d40cf4vboxsync * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
f8a829bc862da0c232b1291990e1e2c990d40cf4vboxsync * Lesser General Public License for more details.
f8a829bc862da0c232b1291990e1e2c990d40cf4vboxsync * You should have received a copy of the GNU Lesser General Public
f8a829bc862da0c232b1291990e1e2c990d40cf4vboxsync * License along with this library; if not, write to the Free Software
f8a829bc862da0c232b1291990e1e2c990d40cf4vboxsync * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
f8a829bc862da0c232b1291990e1e2c990d40cf4vboxsync * Oracle LGPL Disclaimer: For the avoidance of doubt, except that if any license choice
f8a829bc862da0c232b1291990e1e2c990d40cf4vboxsync * other than GPL or LGPL is available it will apply instead, Oracle elects to use only
f8a829bc862da0c232b1291990e1e2c990d40cf4vboxsync * the Lesser General Public License version 2.1 (LGPLv2) at this time for any software where
f8a829bc862da0c232b1291990e1e2c990d40cf4vboxsync * a choice of LGPL license versions is made available with the language indicating
f8a829bc862da0c232b1291990e1e2c990d40cf4vboxsync * that LGPLv2 or any later version may be used, or where a choice of which version
f8a829bc862da0c232b1291990e1e2c990d40cf4vboxsync * of the LGPL is applied is otherwise unspecified.
f8a829bc862da0c232b1291990e1e2c990d40cf4vboxsyncvoid surface_shrc_lock_surf(IWineD3DSurfaceImpl *This)
f84707e750cc4dcb56a0f2608224740e1db86e84vboxsyncvoid surface_shrc_unlock_surf(IWineD3DSurfaceImpl *This)
f8a829bc862da0c232b1291990e1e2c990d40cf4vboxsync /* perform data->texture synchronization */
f8a829bc862da0c232b1291990e1e2c990d40cf4vboxsync IWineD3DSurface_LoadLocation((IWineD3DSurface*)This, SFLAG_INTEXTURE, NULL);
f84707e750cc4dcb56a0f2608224740e1db86e84vboxsyncstatic void surface_cleanup(IWineD3DSurfaceImpl *This)
f84707e750cc4dcb56a0f2608224740e1db86e84vboxsync IWineD3DDeviceImpl *device = This->resource.device;
f84707e750cc4dcb56a0f2608224740e1db86e84vboxsync const struct wined3d_gl_info *gl_info = &device->adapter->gl_info;
f84707e750cc4dcb56a0f2608224740e1db86e84vboxsync /* Need a context to destroy the texture. Use the currently active render
f84707e750cc4dcb56a0f2608224740e1db86e84vboxsync * target, but only if the primary render target exists. Otherwise
f84707e750cc4dcb56a0f2608224740e1db86e84vboxsync * lastActiveRenderTarget is garbage. When destroying the primary render
f84707e750cc4dcb56a0f2608224740e1db86e84vboxsync * target, Uninit3D() will activate a context before doing anything. */
f84707e750cc4dcb56a0f2608224740e1db86e84vboxsync if (device->render_targets && device->render_targets[0])
f84707e750cc4dcb56a0f2608224740e1db86e84vboxsync context = context_acquire(device, NULL, CTXUSAGE_RESOURCELOAD);
f84707e750cc4dcb56a0f2608224740e1db86e84vboxsync /* Release the OpenGL texture. */
f84707e750cc4dcb56a0f2608224740e1db86e84vboxsync TRACE("Deleting texture %u.\n", This->texture_name);
f84707e750cc4dcb56a0f2608224740e1db86e84vboxsync /* Delete the PBO. */
f84707e750cc4dcb56a0f2608224740e1db86e84vboxsync LIST_FOR_EACH_ENTRY_SAFE(entry, entry2, &This->renderbuffers, renderbuffer_entry_t, entry)
f84707e750cc4dcb56a0f2608224740e1db86e84vboxsync gl_info->fbo_ops.glDeleteRenderbuffers(1, &entry->id);
f84707e750cc4dcb56a0f2608224740e1db86e84vboxsync /* Release the DC. */
f8a829bc862da0c232b1291990e1e2c990d40cf4vboxsync /* Release the DIB section. */
UINT surface_calculate_size(const struct wined3d_format_desc *format_desc, UINT alignment, UINT width, UINT height)
size = 0;
return size;
struct blt_info
struct float_rect
static void surface_get_blt_info(GLenum target, const RECT *rect_in, GLsizei w, GLsizei h, struct blt_info *info)
struct float_rect f;
if (rect_in)
switch (target)
case GL_TEXTURE_2D:
case GL_TEXTURE_RECTANGLE_ARB:
if (rect_in)
void draw_textured_quad(IWineD3DSurfaceImpl *src_surface, const RECT *src_rect, const RECT *dst_rect, WINED3DTEXTUREFILTERTYPE Filter)
surface_get_blt_info(src_surface->texture_target, src_rect, src_surface->pow2Width, src_surface->pow2Height, &info);
glEnd();
if (SUCCEEDED(IWineD3DSurface_GetContainer((IWineD3DSurface *)src_surface, &IID_IWineD3DBaseTexture, (void **)&texture)))
UINT width, UINT height, UINT level, BOOL lockable, BOOL discard, WINED3DMULTISAMPLE_TYPE multisample_type,
#ifdef VBOX_WITH_WDDM
, void *pvClientMem
unsigned int resource_size;
if (multisample_quality > 0)
multisample_quality = 0;
switch (surface_type)
case SURFACE_OPENGL:
case SURFACE_GDI:
return WINED3DERR_INVALIDCALL;
#ifdef VBOX_WITH_WDDM
return hr;
#ifdef VBOX_WITH_WDDM
#ifdef VBOX_WITH_WDDM
switch (pool)
case WINED3DPOOL_SCRATCH:
if(!lockable)
case WINED3DPOOL_SYSTEMMEM:
if (!lockable)
FIXME("Called with a pool of SYSTEMMEM and a lockable of FALSE, this is acceptable but unexpected.\n");
case WINED3DPOOL_MANAGED:
case WINED3DPOOL_DEFAULT:
if (lockable && !(usage & (WINED3DUSAGE_DYNAMIC | WINED3DUSAGE_RENDERTARGET | WINED3DUSAGE_DEPTHSTENCIL)))
TRACE("surface %p, memory %p, size %u\n", surface, surface->resource.allocatedMemory, surface->resource.size);
return hr;
#ifdef VBOX_WITH_WDDM
return hr;
if(srgb)
#ifdef VBOX_WITH_WDDM
* from sampler() in state.c. This means we can't touch anything other than
ENTER_GL();
LEAVE_GL();
return TRUE;
return FALSE;
FIXME("Read back converted textures unsupported, format=%s\n", debug_d3dformat(format_desc->format));
ENTER_GL();
LEAVE_GL();
void *mem;
int src_pitch = 0;
int dst_pitch = 0;
if (format_desc->format == WINED3DFMT_P8_UINT && primary_render_target_is_p8(This->resource.device))
LEAVE_GL();
UINT y;
* rendering. If an app does, the SFLAG_DYNLOCK flag will kick in and the memory copy won't be released,
if (srgb)
if (format_desc->heightscale != 1.0f && format_desc->heightscale != 0.0f) height *= format_desc->heightscale;
ENTER_GL();
LEAVE_GL();
#ifdef VBOX_WITH_WDDM
static void surface_upload_data_rect(IWineD3DSurfaceImpl *This, IWineD3DSurfaceImpl *Src, const struct wined3d_gl_info *gl_info,
if (srgb)
if (format_desc->heightscale != 1.0f && format_desc->heightscale != 0.0f) height *= format_desc->heightscale;
ENTER_GL();
LEAVE_GL();
static void surface_allocate_surface(IWineD3DSurfaceImpl *This, const struct wined3d_gl_info *gl_info,
if (srgb)
if (format_desc->heightscale != 1.0f && format_desc->heightscale != 0.0f) height *= format_desc->heightscale;
TRACE("(%p) : Creating surface (target %#x) level %d, d3d format %s, internal format %#x, width %d, height %d, gl format %#x, gl type=%#x\n",
ENTER_GL();
if(This->Flags & (SFLAG_NONPOW2 | SFLAG_DIBSECTION | SFLAG_CONVERTED) || This->resource.allocatedMemory == NULL) {
* allocatedMemory == NULL: Not defined in the extension. Seems to disable client storage effectively
mem = (BYTE *)(((ULONG_PTR) This->resource.heapMemory + (RESOURCE_ALIGNMENT - 1)) & ~(RESOURCE_ALIGNMENT - 1));
#ifdef VBOX_WITH_WDDM
if(enable_client_storage) {
LEAVE_GL();
void surface_set_compatible_renderbuffer(IWineD3DSurface *iface, unsigned int width, unsigned int height) {
if (!renderbuffer) {
return GL_NONE;
return GL_COLOR_ATTACHMENT0;
return GL_BACK;
return GL_FRONT;
return GL_BACK;
#ifdef VBOX_WITH_WDDM
static HRESULT WINAPI IWineD3DSurfaceImpl_LoadLocation(IWineD3DSurface *iface, DWORD flag, const RECT *rect);
IWineD3DSurface_LoadLocation(iface, SFLAG_INSYSMEM, NULL /* no partial locking for textures yet */);
if (dirty_rect)
if (SUCCEEDED(IWineD3DSurface_GetContainer(iface, &IID_IWineD3DBaseTexture, (void **)&baseTexture)))
static BOOL surface_convert_color_to_argb(IWineD3DSurfaceImpl *This, DWORD color, DWORD *argb_color)
case WINED3DFMT_P8_UINT:
case WINED3DFMT_B5G6R5_UNORM:
case WINED3DFMT_B8G8R8_UNORM:
ERR("Unhandled conversion from %s to ARGB!\n", debug_d3dformat(This->resource.format_desc->format));
return FALSE;
return TRUE;
if (!ref)
return ref;
if (IWineD3DSurface_GetContainer(iface, &IID_IWineD3DBaseTexture, (void **)&baseTexture) == WINED3D_OK) {
/* Make sure the texture is reloaded because of the palette change, this kills performance though :( */
ENTER_GL();
LEAVE_GL();
This->resource.heapMemory = HeapAlloc(GetProcessHeap() ,0 , This->resource.size + RESOURCE_ALIGNMENT);
(BYTE *)(((ULONG_PTR) This->resource.heapMemory + (RESOURCE_ALIGNMENT - 1)) & ~(RESOURCE_ALIGNMENT - 1));
ENTER_GL();
GL_EXTCALL(glGetBufferSubDataARB(GL_PIXEL_UNPACK_BUFFER_ARB, 0, This->resource.size, This->resource.allocatedMemory));
LEAVE_GL();
This->resource.heapMemory = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, This->resource.size + RESOURCE_ALIGNMENT);
return FALSE;
(BYTE *)(((ULONG_PTR) This->resource.heapMemory + (RESOURCE_ALIGNMENT - 1)) & ~(RESOURCE_ALIGNMENT - 1));
return TRUE;
ENTER_GL();
LEAVE_GL();
if(!texture) {
ENTER_GL();
#ifdef VBOX_WITH_WDDM
#ifdef VBOX_WITH_WDDM
LEAVE_GL();
static void read_from_framebuffer(IWineD3DSurfaceImpl *This, const RECT *rect, void *dest, UINT pitch)
if(!warned) {
* Certain graphics drivers seem to dislike some enabled states when reading from opengl, the blitting usage
* should help here. Furthermore unlockrect will need the context set up for blitting. The context manager will find
ENTER_GL();
if(!rect) {
case WINED3DFMT_P8_UINT:
if(!mem) {
LEAVE_GL();
glReadPixels(local_rect.left, (!srcIsUpsideDown) ? (This->currentDesc.Height - local_rect.bottom) : local_rect.top ,
if(!srcIsUpsideDown) {
if(!srcIsUpsideDown) {
if(!row) {
LEAVE_GL();
LEAVE_GL();
/* For P8 textures we need to perform an inverse palette lookup. This is done by searching for a palette
* index which matches the RGB value. Note this isn't guaranteed to work when there are multiple entries for
* In case of P8 render targets, the index is stored in the alpha component so no conversion is needed.
if (This->resource.format_desc->format == WINED3DFMT_P8_UINT && !primary_render_target_is_p8(myDevice))
/* Activate the surface to read from. In some situations it isn't the currently active target(e.g. backbuffer
* locking during offscreen rendering). RESOURCELOAD is ok because glCopyTexSubImage2D isn't affected by any
ENTER_GL();
LEAVE_GL();
ENTER_GL();
LEAVE_GL();
ENTER_GL();
LEAVE_GL();
ENTER_GL();
LEAVE_GL();
void surface_prepare_texture(IWineD3DSurfaceImpl *surface, const struct wined3d_gl_info *gl_info, BOOL srgb)
/* Performance optimization: Count how often a surface is locked, if it is locked regularly do not throw away the system memory copy.
* This avoids the need to download the surface from opengl all the time. The surface is still downloaded if the opengl texture is
/* MAXLOCKCOUNT is defined in wined3d_private.h */
ENTER_GL();
#ifndef VBOX_WITH_WDDM
GL_EXTCALL(glBufferDataARB(GL_PIXEL_UNPACK_BUFFER_ARB, This->resource.size + 4, This->resource.allocatedMemory, GL_STREAM_DRAW_ARB));
LEAVE_GL();
This->resource.heapMemory = HeapAlloc(GetProcessHeap() ,0 , This->resource.size + RESOURCE_ALIGNMENT);
(BYTE *)(((ULONG_PTR) This->resource.heapMemory + (RESOURCE_ALIGNMENT - 1)) & ~(RESOURCE_ALIGNMENT - 1));
static HRESULT WINAPI IWineD3DSurfaceImpl_LockRect(IWineD3DSurface *iface, WINED3DLOCKED_RECT* pLockedRect, CONST RECT* pRect, DWORD Flags) {
TRACE("(%p) : rect@%p flags(%08x), output lockedRect@%p, memory@%p\n", This, pRect, Flags, pLockedRect, This->resource.allocatedMemory);
return WINED3DERR_INVALIDCALL;
#ifdef VBOX_WITH_WDDM
goto lock_end;
goto lock_end;
ENTER_GL();
This->resource.allocatedMemory = GL_EXTCALL(glMapBufferARB(GL_PIXEL_UNPACK_BUFFER_ARB, GL_READ_WRITE_ARB));
LEAVE_GL();
if (SUCCEEDED(IWineD3DSurface_GetContainer(iface, &IID_IWineD3DBaseTexture, (void **)&pBaseTexture))) {
#ifdef VBOX_WITH_WDDM
return hr;
static void flush_to_framebuffer_drawpixels(IWineD3DSurfaceImpl *This, GLenum fmt, GLenum type, UINT bpp, const BYTE *mem) {
ENTER_GL();
/* When the surface is locked we only have to refresh the locked part else we need to update the whole image */
LEAVE_GL();
return WINEDDERR_NOTLOCKED;
ENTER_GL();
LEAVE_GL();
goto unlock_end;
if ((This->Flags & SFLAG_SWAPCHAIN) || (myDevice->render_targets && iface == myDevice->render_targets[0]))
if(!warned) {
ERR("The application tries to write to the render target, but render target locking is disabled\n");
goto unlock_end;
case RTL_READTEX:
IWineD3DSurface_LoadLocation(iface, SFLAG_INTEXTURE, NULL /* partial texture loading not supported yet */);
case RTL_READDRAW:
if(!fullsurface) {
/* Partial rectangle tracking is not commonly implemented, it is only done for render targets. Overwrite
* the flags to bring them back into a sane state. INSYSMEM was set before to tell LoadLocation where
* to read the rectangle from. Indrawable is set because all modifications from the partial sysmem copy
* are written back to the drawable, thus the surface is merged again in the drawable. The sysmem copy is
#ifdef VBOX_WITH_WDDM
return WINED3D_OK;
ENTER_GL();
#ifdef VBOX_WITH_WDDM
LEAVE_GL();
return WINEDDERR_NODC;
return WINEDDERR_DCALREADYCREATED;
return WINED3DERR_INVALIDCALL;
&lock,
NULL,
/* Sync the DIB with the PBO. This can't be done earlier because LockRect activates the allocatedMemory */
return hr;
#ifdef VBOX_WITH_WDDM
swapchain = (IWineD3DSwapChainImpl *)This->resource.device->swapchains[This->resource.device->NumberOfSwapChains-1];
if (pal) {
return WINED3D_OK;
return WINEDDERR_NODC;
return WINEDDERR_NODC;
return WINED3D_OK;
HRESULT d3dfmt_get_conv(IWineD3DSurfaceImpl *This, BOOL need_alpha_ck, BOOL use_texturing, struct wined3d_format_desc *desc, CONVERT_TYPES *convert)
case WINED3DFMT_P8_UINT:
if (!((blit_supported && device->render_targets && This == (IWineD3DSurfaceImpl*)device->render_targets[0]))
if(colorkey_active) {
case WINED3DFMT_B2G3R3_UNORM:
if (colorkey_active) {
case WINED3DFMT_B5G6R5_UNORM:
if (colorkey_active) {
if (colorkey_active) {
case WINED3DFMT_B8G8R8_UNORM:
if (colorkey_active) {
if (colorkey_active) {
return WINED3D_OK;
if (!pal)
/* In DirectDraw the palette is a property of the surface, there are no such things as device palettes. */
if (index_in_alpha)
/* Direct3D >= 8 palette usage style: P8 textures use device palettes, palette entry format is A8R8G8B8,
if (index_in_alpha)
switch (convert) {
case NO_CONVERSION:
case CONVERT_PALETTED:
case CONVERT_PALETTED_CK:
for (y = 0; y < height; y++)
for (x = 0; x < width; x++) {
case CONVERT_CK_565:
for (y = 0; y < height; y++) {
for (x = 0; x < width; x++ ) {
Dest++;
case CONVERT_CK_5551:
for (y = 0; y < height; y++) {
for (x = 0; x < width; x++ ) {
Dest++;
case CONVERT_CK_RGB24:
for (y = 0; y < height; y++)
for (x = 0; x < width; x++) {
case CONVERT_RGB32_888:
for (y = 0; y < height; y++)
for (x = 0; x < width; x++) {
return WINED3D_OK;
return FALSE;
return FALSE;
return TRUE;
/* Make sure the texture is reloaded because of the color key change, this kills performance though :( */
return WINED3D_OK;
return WINED3DERR_INVALIDCALL;
static unsigned int gen = 0;
++gen;
return WINED3D_OK;
if (IWineD3DSurface_GetContainer(iface, &IID_IWineD3DBaseTexture, (void **)&baseTexture) == WINED3D_OK) {
ENTER_GL();
if (!*name) {
#ifdef VBOX_WITH_WDDM
#ifdef VBOX_WITH_WDDM
} else if (*name) {
LEAVE_GL();
#include <errno.h>
#include <stdio.h>
static HRESULT WINAPI IWineD3DSurfaceImpl_SaveSnapshot(IWineD3DSurface *iface, const char* filename)
char *allocatedMemory;
const char *textureRow;
/* check to see if we're a 'virtual' texture, e.g. we're not a pbuffer of texture, we're a back buffer*/
ENTER_GL();
NULL);
LEAVE_GL();
ENTER_GL();
glGetTexImage(GL_TEXTURE_2D, This->texture_level, GL_RGBA, GL_UNSIGNED_INT_8_8_8_8_REV, allocatedMemory);
if (tmpTexture) {
LEAVE_GL();
if (NULL == f) {
return WINED3DERR_INVALIDCALL;
/* Save the data out to a TGA file because 1: it's an easy raw format, 2: it supports an alpha channel */
TRACE("(%p) opened %s with format %s\n", This, filename, debug_d3dformat(This->resource.format_desc->format));
fputc(0,f);
fputc(0,f);
fputc(0,f);
fputc(0,f);
fputc(0,f);
fputc(0,f);
fputc(0,f);
fputc(0,f);
fputc(0,f);
fputc(0,f);
fputc(0,f);
/* if the data is upside down if we've fetched it from a back buffer, so it needs flipping again to make it the correct way up */
if(swapChain)
for (y = 0 ; y < height; y++) {
for (i = 0; i < width; i++) {
if(swapChain)
fclose(f);
if(swapChain) {
return WINED3D_OK;
TRACE("(%p) : glFormat %d, glFormatInternal %d, glType %d\n", This, This->resource.format_desc->glFormat,
return hr;
return WINED3DERR_INVALIDCALL;
return WINED3D_OK;
void* tmp;
static HRESULT WINAPI IWineD3DSurfaceImpl_Flip(IWineD3DSurface *iface, IWineD3DSurface *override, DWORD Flags) {
return WINEDDERR_NOTFLIPPABLE;
return WINED3D_OK;
if(override) {
if(!swapchain) {
return WINEDDERR_NOTFLIPPABLE;
/* Just overwrite the swapchain presentation interval. This is ok because only ddraw apps can call Flip,
if((Flags & (WINEDDFLIP_NOVSYNC | WINEDDFLIP_INTERVAL2 | WINEDDFLIP_INTERVAL3 | WINEDDFLIP_INTERVAL4)) == 0) {
return hr;
#ifdef VBOX_WITH_WDDM
# define VBOX_WINE_TEXDIRECT_USE_RESOURCELOAD
static inline BOOL fb_copy_to_texture_direct(IWineD3DSurfaceImpl *This, IWineD3DSurface *SrcSurface,
/* Make sure that the top pixel is always above the bottom pixel, and keep a separate upside down flag
#ifdef DEBUG_misha
if (isSrcOffscreen)
FIXME("Doing a pixel by pixel copy from the framebuffer to a texture, expect major performance issues\n");
return FALSE;
else if (!surface_is_offscreen((IWineD3DSurface*)This)) context = context_acquire(myDevice, (IWineD3DSurface *) This, CTXUSAGE_RESOURCELOAD);
ENTER_GL();
if(isSrcOffscreen) {
if (fNoStretching)
LEAVE_GL();
return TRUE;
static inline void fb_copy_to_texture_hwstretch(IWineD3DSurfaceImpl *This, IWineD3DSurface *SrcSurface,
ENTER_GL();
if(noBackBufferBackup) {
/* Backup the back buffer and copy the source buffer into a texture to draw an upside down stretched quad. If
/* For now invalidate the texture copy of the back buffer. Drawable and sysmem copy are untouched */
/* Make sure that the top pixel is always above the bottom pixel, and keep a separate upside down flag
if (src_offscreen)
fbheight);
IWineD3DSurface_GetContainer((IWineD3DSurface *)SrcSurface, &IID_IWineD3DSwapChain, (void **)&src_swapchain);
/* TODO: Only copy the part that will be read. Use src_rect->left, src_rect->bottom as origin, but with the width watch
fbheight);
if(upsidedown) {
glEnd();
if(backup) {
glVertex2i(0, 0);
glEnd();
if(backup) {
LEAVE_GL();
if (wined3d_settings.strict_draw_ordering) wglFlush(); /* Flush to ensure ordering across contexts. */
return WINED3DERR_INVALIDCALL;
IWineD3DSurface_GetContainer( (IWineD3DSurface *) This, &IID_IWineD3DSwapChain, (void **)&dstSwapchain);
if(Src) {
return WINED3DERR_INVALIDCALL;
IWineD3DSurface_GetContainer( (IWineD3DSurface *) Src, &IID_IWineD3DSwapChain, (void **)&srcSwapchain);
SrcSurface != myDevice->render_targets[0] && This != (IWineD3DSurfaceImpl *) myDevice->render_targets[0]) {
return WINED3DERR_INVALIDCALL;
return WINED3DERR_INVALIDCALL;
/* The only case where both surfaces on a swapchain are supported is a back buffer -> front buffer blit on the same swapchain */
((IWineD3DSurface *) This == dstSwapchain->frontBuffer) && SrcSurface == dstSwapchain->backBuffer[0]) {
#ifdef VBOX_WITH_WDDM
* This path will only be entered for d3d7 and ddraw apps, because d3d8/9 offer no way to blit TO the front buffer
return WINED3D_OK;
return WINED3DERR_INVALIDCALL;
return WINED3DERR_INVALIDCALL;
return WINED3DERR_INVALIDCALL;
} else if(dstSwapchain) {
return WINED3DERR_INVALIDCALL;
return WINED3DERR_INVALIDCALL;
return WINED3DERR_INVALIDCALL;
* -> If the app wants a image that is scaled on the x axis, and the destination rectangle is smaller
* -> If the app wants a scaled image with a dest rect that is bigger than the fb, it has to be copied
* If EXT_framebuffer_blit is supported that can be used instead. Note that EXT_framebuffer_blit implies
* FBO support, so it doesn't really make sense to try and make it work with different offscreen rendering
/* blit framebuffer might be buggy for some GPUs, try if fb_copy_to_texture_direct can do it quickly */
if (!fb_copy_to_texture_direct(This, SrcSurface, &src_rect, &dst_rect, Filter, TRUE /* fals only */))
fb_copy_to_texture_direct(This, SrcSurface, &src_rect, &dst_rect, Filter, FALSE /* do it alwais */);
return WINED3D_OK;
} else if(Src) {
return WINED3D_OK;
#ifndef VBOX_WITH_WDDM
UINT h;
#ifdef VBOX_WITH_WDDM
return WINED3DERR_INVALIDCALL;
ENTER_GL();
LEAVE_GL();
#ifdef VBOX_WITH_WDDM
return WINED3D_OK;
return WINED3DERR_INVALIDCALL;
return WINED3DERR_INVALIDCALL;
return WINED3DERR_INVALIDCALL;
float depth;
case WINED3DFMT_D16_UNORM:
case WINED3DFMT_X8D24_UNORM:
case WINED3DFMT_D32_UNORM:
return WINED3DERR_INVALIDCALL;
#ifdef VBOX_WITH_WDDM
return WINED3DERR_INVALIDCALL;
return WINED3DERR_INVALIDCALL;
return WINED3DERR_INVALIDCALL;
return WINED3DERR_INVALIDCALL;
return WINED3DERR_INVALIDCALL;
return WINED3DERR_INVALIDCALL;
return WINED3DERR_INVALIDCALL;
return WINED3DERR_INVALIDCALL;
return WINED3DERR_INVALIDCALL;
if(!mem) {
return WINED3DERR_OUTOFVIDEOMEMORY;
int outpitch;
if(!mem) {
return WINED3DERR_OUTOFVIDEOMEMORY;
d3dfmt_convert_surface(Src->resource.allocatedMemory, mem, srcPitch, srcWidth, srcHeight, outpitch, convert, Src);
ENTER_GL();
LEAVE_GL();
ENTER_GL();
LEAVE_GL();
IWineD3DSurface_ModifyLocation((IWineD3DSurface *)This, srgb ? SFLAG_INSRGBTEX : SFLAG_INTEXTURE, TRUE);
return WINED3D_OK;
static HRESULT WINAPI IWineD3DSurfaceImpl_Blt(IWineD3DSurface *iface, const RECT *DestRect, IWineD3DSurface *SrcSurface,
return WINEDDERR_SURFACEBUSY;
#ifdef VBOX_WITH_WDDM
if(iface == myDevice->stencilBufferTarget || (SrcSurface && SrcSurface == myDevice->stencilBufferTarget)) {
TRACE("Attempt to access the depth stencil surface in a BeginScene / EndScene pair, returning WINED3DERR_INVALIDCALL\n");
goto end;
} else if(IWineD3DSurfaceImpl_BltZ(This, DestRect, SrcSurface, SrcRect, Flags, DDBltFx) == WINED3D_OK) {
goto end;
if(IWineD3DSurfaceImpl_BltOverride(This, DestRect, SrcSurface, SrcRect, Flags, DDBltFx, Filter) == WINED3D_OK)
goto end;
#ifdef VBOX_WITH_WDDM
if (IWineD3DSurfaceImpl_BltSys2Vram(This, DestRect, SrcSurface, SrcRect, Flags, DDBltFx, Filter) == WINED3D_OK)
goto end;
end:
#ifdef VBOX_WITH_WDDM
return hr;
return WINEDDERR_SURFACEBUSY;
TRACE("Attempt to access the depth stencil surface in a BeginScene / EndScene pair, returning WINED3DERR_INVALIDCALL\n");
return WINED3DERR_INVALIDCALL;
#ifdef VBOX_WITH_WDDM
if(IWineD3DSurfaceImpl_BltOverride(This, &DstRect, Source, &SrcRect, Flags, NULL, WINED3DTEXF_POINT) == WINED3D_OK)
goto end;
end:
#ifdef VBOX_WITH_WDDM
return hr;
/* Make sure the texture is up to date. This call doesn't do anything if the texture is already up to date. */
return WINED3D_OK;
#ifdef VBOX_WITH_WDDM
static HRESULT WINAPI IWineD3DSurfaceImpl_LoadLocation(IWineD3DSurface *iface, DWORD flag, const RECT *rect);
if (gl_info->supported[ARB_TEXTURE_NON_POWER_OF_TWO] || gl_info->supported[WINE_NORMALIZED_TEXRECT])
return WINED3DERR_NOTAVAILABLE;
if ((This->pow2Width > gl_info->limits.texture_size || This->pow2Height > gl_info->limits.texture_size)
1: Do the same as we do with nonpow 2 and scale the texture, (any texture ops would require the texture to be scaled which is potentially slow)
4: Create the surface, but allow it to be used only for DirectDraw Blts. Some apps(e.g. Swat 3) create textures with a Height of 16 and a Width > 3000 and blt 16x16 letter areas from them to the render target.
return WINED3DERR_NOTAVAILABLE;
is used in combination with texture uploads (RTL_READTEX/RTL_TEXTEX). The reason is that EXT_PALETTED_TEXTURE
return WINED3D_OK;
glViewport(0, 0, w, h);
glEnd();
glPopAttrib();
void surface_load_ds_location(IWineD3DSurface *iface, struct wined3d_context *context, DWORD location)
ENTER_GL();
LEAVE_GL();
if (wined3d_settings.strict_draw_ordering) wglFlush(); /* Flush to ensure ordering across contexts. */
ENTER_GL();
LEAVE_GL();
if (wined3d_settings.strict_draw_ordering) wglFlush(); /* Flush to ensure ordering across contexts. */
static void WINAPI IWineD3DSurfaceImpl_ModifyLocation(IWineD3DSurface *iface, DWORD flag, BOOL persistent) {
if(persistent) {
if (IWineD3DSurface_GetContainer(iface, &IID_IWineD3DBaseTexture, (void **)&texture) == WINED3D_OK) {
if((This->Flags & (SFLAG_INTEXTURE | SFLAG_INSRGBTEX)) && (flag & (SFLAG_INTEXTURE | SFLAG_INSRGBTEX))) {
if (IWineD3DSurface_GetContainer(iface, &IID_IWineD3DBaseTexture, (void **)&texture) == WINED3D_OK) {
#ifdef VBOX_WITH_WDDM
ENTER_GL();
LEAVE_GL();
#ifdef VBOX_WITH_WDDM
static HRESULT WINAPI IWineD3DSurfaceImpl_LoadLocation(IWineD3DSurface *iface, DWORD flag, const RECT *rect) {
if(rect) {
#ifdef VBOX_WITH_WDDM
goto post_process;
return WINED3D_OK;
return WINED3DERR_DEVICELOST;
int byte_count;
d3dfmt_get_conv(This, FALSE /* We need color keying */, FALSE /* We won't use textures */, &desc, &convert);
if(!mem) {
return WINED3DERR_OUTOFVIDEOMEMORY;
d3dfmt_convert_surface(This->resource.allocatedMemory, mem, pitch, width, height, outpitch, convert, This);
if(srgb) {
if(!mem) {
return WINED3DERR_OUTOFVIDEOMEMORY;
if(!mem) {
return WINED3DERR_OUTOFVIDEOMEMORY;
d3dfmt_convert_surface(This->resource.allocatedMemory, mem, pitch, width, height, outpitch, convert, This);
ENTER_GL();
LEAVE_GL();
ENTER_GL();
LEAVE_GL();
#ifdef VBOX_WITH_WDDM
return WINED3D_OK;
static HRESULT WINAPI IWineD3DSurfaceImpl_SetContainer(IWineD3DSurface *iface, IWineD3DBase *container)
if(container) {
if(swapchain) {
return SURFACE_OPENGL;
return WINED3D_OK;
return hr;
static void ffp_blit_p8_upload_palette(IWineD3DSurfaceImpl *surface, const struct wined3d_gl_info *gl_info)
ENTER_GL();
GL_EXTCALL(glColorTableEXT(surface->texture_target, GL_RGBA, 256, GL_RGBA, GL_UNSIGNED_BYTE, table));
LEAVE_GL();
ENTER_GL();
LEAVE_GL();
return WINED3D_OK;
ENTER_GL();
LEAVE_GL();
return FALSE;
return TRUE;
return FALSE;
return FALSE;
return TRUE;
return TRUE;
return FALSE;
static HRESULT ffp_blit_color_fill(IWineD3DDeviceImpl *device, IWineD3DSurfaceImpl *dst_surface, const RECT *dst_rect, DWORD fill_color)
return WINED3D_OK;
return WINED3D_OK;
return TRUE;
return FALSE;
static HRESULT cpu_blit_color_fill(IWineD3DDeviceImpl *device, IWineD3DSurfaceImpl *dst_surface, const RECT *dst_rect, DWORD fill_color)
BltFx.u5.dwFillColor = color_convert_argb_to_fmt(fill_color, dst_surface->resource.format_desc->format);
return IWineD3DBaseSurfaceImpl_Blt((IWineD3DSurface*)dst_surface, dst_rect, NULL, NULL, WINEDDBLT_COLORFILL, &BltFx, WINED3DTEXF_POINT);
return FALSE;
return FALSE;
return FALSE;
if(!((src_format_desc->Flags & WINED3DFMT_FLAG_FBO_ATTACHABLE) || (src_usage & WINED3DUSAGE_RENDERTARGET))
&& ((dst_format_desc->Flags & WINED3DFMT_FLAG_FBO_ATTACHABLE) || (dst_usage & WINED3DUSAGE_RENDERTARGET)))
return FALSE;
return FALSE;
return FALSE;
return TRUE;