wined3d: Use GL_APPLE_client_storage if available.
This commit is contained in:
parent
f9ee2355d0
commit
4f5d33311b
|
@ -352,6 +352,14 @@ WineD3DContext *CreateContext(IWineD3DDeviceImpl *This, IWineD3DSurfaceImpl *tar
|
|||
glPixelStorei(GL_UNPACK_ALIGNMENT, SURFACE_ALIGNMENT);
|
||||
checkGLcall("glPixelStorei(GL_UNPACK_ALIGNMENT, SURFACE_ALIGNMENT);");
|
||||
|
||||
if(GL_SUPPORT(APPLE_CLIENT_STORAGE)) {
|
||||
/* Most textures will use client storage if supported. Exceptions are non-native power of 2 textures
|
||||
* and textures in DIB sections(due to the memory protection).
|
||||
*/
|
||||
glPixelStorei(GL_UNPACK_CLIENT_STORAGE_APPLE, GL_TRUE);
|
||||
checkGLcall("glPixelStorei(GL_UNPACK_CLIENT_STORAGE_APPLE, GL_TRUE)");
|
||||
}
|
||||
|
||||
if(oldDrawable && oldCtx) {
|
||||
glXMakeCurrent(display, oldDrawable, oldCtx);
|
||||
}
|
||||
|
|
|
@ -5475,6 +5475,7 @@ static void updateSurfaceDesc(IWineD3DSurfaceImpl *surface, WINED3DPRESENT_PARAM
|
|||
glDeleteTextures(1, &surface->glDescription.textureName);
|
||||
LEAVE_GL();
|
||||
surface->glDescription.textureName = 0;
|
||||
surface->Flags &= ~SFLAG_CLIENT;
|
||||
}
|
||||
if(surface->pow2Width != pPresentationParameters->BackBufferWidth ||
|
||||
surface->pow2Height != pPresentationParameters->BackBufferHeight) {
|
||||
|
|
|
@ -167,6 +167,11 @@ static void surface_upload_data(IWineD3DSurfaceImpl *This, GLsizei width, GLsize
|
|||
if (!GL_SUPPORT(EXT_TEXTURE_COMPRESSION_S3TC)) {
|
||||
FIXME("Using DXT1/3/5 without advertized support\n");
|
||||
} else {
|
||||
if(GL_SUPPORT(APPLE_CLIENT_STORAGE)) {
|
||||
/* Neither NONPOW2, DIBSECTION nor OVERSIZE flags can be set on compressed textures */
|
||||
This->Flags |= SFLAG_CLIENT;
|
||||
}
|
||||
|
||||
TRACE("(%p) : Calling glCompressedTexSubImage2D w %d, h %d, data %p\n", This, width, height, data);
|
||||
ENTER_GL();
|
||||
/* glCompressedTexSubImage2D for uploading and glTexImage2D for allocating does not work well on some drivers(r200 dri, MacOS ATI driver)
|
||||
|
@ -188,6 +193,8 @@ static void surface_upload_data(IWineD3DSurfaceImpl *This, GLsizei width, GLsize
|
|||
}
|
||||
|
||||
static void surface_allocate_surface(IWineD3DSurfaceImpl *This, GLenum internal, GLsizei width, GLsizei height, GLenum format, GLenum type) {
|
||||
BOOL enable_client_storage = FALSE;
|
||||
|
||||
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", This,
|
||||
This->glDescription.target, This->glDescription.level, debug_d3dformat(This->resource.format), internal, width, height, format, type);
|
||||
|
||||
|
@ -201,9 +208,32 @@ static void surface_allocate_surface(IWineD3DSurfaceImpl *This, GLenum internal,
|
|||
|
||||
ENTER_GL();
|
||||
|
||||
glTexImage2D(This->glDescription.target, This->glDescription.level, internal, width, height, 0, format, type, NULL);
|
||||
if(GL_SUPPORT(APPLE_CLIENT_STORAGE)) {
|
||||
if(This->Flags & (SFLAG_NONPOW2 | SFLAG_DIBSECTION | SFLAG_OVERSIZE | SFLAG_CONVERTED) || This->resource.allocatedMemory == NULL) {
|
||||
/* In some cases we want to disable client storage.
|
||||
* SFLAG_NONPOW2 has a bigger opengl texture than the client memory, and different pitches
|
||||
* SFLAG_DIBSECTION: Dibsections may have read / write protections on the memory. Avoid issues...
|
||||
* SFLAG_OVERSIZE: The gl texture is smaller than the allocated memory
|
||||
* SFLAG_CONVERTED: The conversion destination memory is freed after loading the surface
|
||||
* allocatedMemory == NULL: Not defined in the extension. Seems to disable client storage effectively
|
||||
*/
|
||||
glPixelStorei(GL_UNPACK_CLIENT_STORAGE_APPLE, GL_FALSE);
|
||||
checkGLcall("glPixelStorei(GL_UNPACK_CLIENT_STORAGE_APPLE, GL_FALSE)");
|
||||
This->Flags &= SFLAG_CLIENT;
|
||||
enable_client_storage = TRUE;
|
||||
} else {
|
||||
This->Flags |= SFLAG_CLIENT;
|
||||
/* Below point opengl to our allocated texture memory */
|
||||
}
|
||||
}
|
||||
glTexImage2D(This->glDescription.target, This->glDescription.level, internal, width, height, 0, format, type,
|
||||
This->Flags & SFLAG_CLIENT ? This->resource.allocatedMemory : NULL);
|
||||
checkGLcall("glTexImage2D");
|
||||
|
||||
if(enable_client_storage) {
|
||||
glPixelStorei(GL_UNPACK_CLIENT_STORAGE_APPLE, GL_TRUE);
|
||||
checkGLcall("glPixelStorei(GL_UNPACK_CLIENT_STORAGE_APPLE, GL_TRUE)");
|
||||
}
|
||||
LEAVE_GL();
|
||||
}
|
||||
|
||||
|
@ -1203,6 +1233,7 @@ HRESULT WINAPI IWineD3DSurfaceImpl_GetDC(IWineD3DSurface *iface, HDC *pHDC) {
|
|||
if(!This->hDC) {
|
||||
int extraline = 0;
|
||||
SYSTEM_INFO sysInfo;
|
||||
void *oldmem = This->resource.allocatedMemory;
|
||||
|
||||
switch (This->bytesPerPixel) {
|
||||
case 2:
|
||||
|
@ -1306,7 +1337,6 @@ HRESULT WINAPI IWineD3DSurfaceImpl_GetDC(IWineD3DSurface *iface, HDC *pHDC) {
|
|||
if(This->resource.allocatedMemory) {
|
||||
memcpy(This->dib.bitmap_data, This->resource.allocatedMemory, b_info->bmiHeader.biSizeImage);
|
||||
/* We won't need that any more */
|
||||
HeapFree(GetProcessHeap(), 0, This->resource.allocatedMemory);
|
||||
} else {
|
||||
/* This is to make LockRect read the gl Texture although memory is allocated */
|
||||
This->Flags &= ~SFLAG_INSYSMEM;
|
||||
|
@ -1326,6 +1356,11 @@ HRESULT WINAPI IWineD3DSurfaceImpl_GetDC(IWineD3DSurface *iface, HDC *pHDC) {
|
|||
FALSE);
|
||||
|
||||
This->Flags |= SFLAG_DIBSECTION;
|
||||
|
||||
if(This->Flags & SFLAG_CLIENT) {
|
||||
IWineD3DSurface_PreLoad(iface);
|
||||
}
|
||||
HeapFree(GetProcessHeap(), 0, oldmem);
|
||||
}
|
||||
|
||||
/* Lock the surface */
|
||||
|
@ -1874,6 +1909,9 @@ static HRESULT WINAPI IWineD3DSurfaceImpl_LoadTexture(IWineD3DSurface *iface) {
|
|||
surface_upload_data(This, This->currentDesc.Width, This->currentDesc.Height, format, type, mem);
|
||||
}
|
||||
} else {
|
||||
/* When making the realloc conditional, keep in mind that GL_APPLE_client_storage may be in use, and This->resource.allocatedMemory
|
||||
* changed. So also keep track of memory changes. In this case the texture has to be reallocated
|
||||
*/
|
||||
surface_allocate_surface(This, internal, This->glRect.right - This->glRect.left, This->glRect.bottom - This->glRect.top, format, type);
|
||||
if (mem) {
|
||||
surface_upload_data(This, This->glRect.right - This->glRect.left, This->glRect.bottom - This->glRect.top, format, type, mem);
|
||||
|
@ -2161,6 +2199,7 @@ HRESULT WINAPI IWineD3DSurfaceImpl_SetMem(IWineD3DSurface *iface, void *Mem) {
|
|||
}
|
||||
|
||||
if(Mem && Mem != This->resource.allocatedMemory) {
|
||||
void *release = NULL;
|
||||
|
||||
/* Do I have to copy the old surface content? */
|
||||
if(This->Flags & SFLAG_DIBSECTION) {
|
||||
|
@ -2177,14 +2216,31 @@ HRESULT WINAPI IWineD3DSurfaceImpl_SetMem(IWineD3DSurface *iface, void *Mem) {
|
|||
This->hDC = NULL;
|
||||
This->Flags &= ~SFLAG_DIBSECTION;
|
||||
} else if(!(This->Flags & SFLAG_USERPTR)) {
|
||||
HeapFree(GetProcessHeap(), 0, This->resource.allocatedMemory);
|
||||
release = This->resource.allocatedMemory;
|
||||
}
|
||||
This->resource.allocatedMemory = Mem;
|
||||
This->Flags |= SFLAG_USERPTR;
|
||||
This->Flags |= SFLAG_USERPTR | SFLAG_INSYSMEM;
|
||||
|
||||
/* Now the surface memory is most up do date. Invalidate drawable and texture */
|
||||
This->Flags &= ~(SFLAG_INDRAWABLE | SFLAG_INTEXTURE);
|
||||
|
||||
/* For client textures opengl has to be notified */
|
||||
if(This->Flags & SFLAG_CLIENT) {
|
||||
IWineD3DSurface_PreLoad(iface);
|
||||
/* And hope that the app behaves correctly and did not free the old surface memory before setting a new pointer */
|
||||
}
|
||||
|
||||
/* Now free the old memory if any */
|
||||
HeapFree(GetProcessHeap(), 0, release);
|
||||
} else if(This->Flags & SFLAG_USERPTR) {
|
||||
/* Lockrect and GetDC will re-create the dib section and allocated memory */
|
||||
This->resource.allocatedMemory = NULL;
|
||||
This->Flags &= ~SFLAG_USERPTR;
|
||||
|
||||
if(This->Flags & SFLAG_CLIENT) {
|
||||
/* This respecifies an empty texture and opengl knows that the old memory is gone */
|
||||
IWineD3DSurface_PreLoad(iface);
|
||||
}
|
||||
}
|
||||
return WINED3D_OK;
|
||||
}
|
||||
|
@ -3200,6 +3256,13 @@ static HRESULT WINAPI IWineD3DSurfaceImpl_PrivateSetup(IWineD3DSurface *iface) {
|
|||
This->glRect.bottom = This->pow2Height;
|
||||
}
|
||||
|
||||
if(GL_SUPPORT(APPLE_CLIENT_STORAGE) && This->resource.allocatedMemory == NULL) {
|
||||
/* Make sure that memory is allocated from the start if we are going to use GL_APPLE_client_storage.
|
||||
* Otherwise a glTexImage2D with a NULL pointer may be done, e.g. when blitting or with offscreen render
|
||||
* targets, thus the client storage wouldn't be used for that texture
|
||||
*/
|
||||
This->resource.allocatedMemory = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, This->resource.size + 4);
|
||||
}
|
||||
return WINED3D_OK;
|
||||
}
|
||||
|
||||
|
|
|
@ -291,7 +291,11 @@ static HRESULT WINAPI IWineD3DVolumeImpl_LoadTexture(IWineD3DVolume *iface, GLen
|
|||
checkGLcall("glTexImage3D");
|
||||
} else
|
||||
WARN("This OpenGL implementation doesn't support 3D textures\n");
|
||||
|
||||
|
||||
/* When adding code releasing This->resource.allocatedMemory to save data keep in mind that
|
||||
* GL_UNPACK_CLIENT_STORAGE_APPLE is enabled by default if supported(GL_APPLE_client_storage).
|
||||
* Thus do not release This->resource.allocatedMemory if GL_APPLE_client_storage is supported.
|
||||
*/
|
||||
return WINED3D_OK;
|
||||
|
||||
}
|
||||
|
|
|
@ -1117,6 +1117,7 @@ HRESULT WINAPI IWineD3DSurfaceImpl_UpdateOverlay(IWineD3DSurface *iface, RECT *S
|
|||
#define SFLAG_LOST 0x00002000 /* Surface lost flag for DDraw */
|
||||
#define SFLAG_USERPTR 0x00004000 /* The application allocated the memory for this surface */
|
||||
#define SFLAG_GLCKEY 0x00008000 /* The gl texture was created with a color key */
|
||||
#define SFLAG_CLIENT 0x00010000 /* GL_APPLE_client_storage is used on that texture */
|
||||
|
||||
/* In some conditions the surface memory must not be freed:
|
||||
* SFLAG_OVERSIZE: Not all data can be kept in GL
|
||||
|
@ -1125,6 +1126,7 @@ HRESULT WINAPI IWineD3DSurfaceImpl_UpdateOverlay(IWineD3DSurface *iface, RECT *S
|
|||
* SFLAG_LOCKED: The app requires access to the surface data
|
||||
* SFLAG_DYNLOCK: Avoid freeing the data for performance
|
||||
* SFLAG_DYNCHANGE: Same reason as DYNLOCK
|
||||
* SFLAG_CLIENT: OpenGL uses our memory as backup
|
||||
*/
|
||||
#define SFLAG_DONOTFREE (SFLAG_OVERSIZE | \
|
||||
SFLAG_CONVERTED | \
|
||||
|
@ -1132,7 +1134,8 @@ HRESULT WINAPI IWineD3DSurfaceImpl_UpdateOverlay(IWineD3DSurface *iface, RECT *S
|
|||
SFLAG_LOCKED | \
|
||||
SFLAG_DYNLOCK | \
|
||||
SFLAG_DYNCHANGE | \
|
||||
SFLAG_USERPTR)
|
||||
SFLAG_USERPTR | \
|
||||
SFLAG_CLIENT)
|
||||
|
||||
BOOL CalculateTexRect(IWineD3DSurfaceImpl *This, RECT *Rect, float glTexCoord[4]);
|
||||
|
||||
|
|
Loading…
Reference in New Issue