Commit fcb83e71 authored by Stefan Dösinger's avatar Stefan Dösinger Committed by Alexandre Julliard

wined3d: Activate a context before doing opengl calls.

parent 9789f993
...@@ -96,9 +96,12 @@ ULONG WINAPI IWineD3DBaseTextureImpl_Release(IWineD3DBaseTexture *iface) { ...@@ -96,9 +96,12 @@ ULONG WINAPI IWineD3DBaseTextureImpl_Release(IWineD3DBaseTexture *iface) {
/* class static */ /* class static */
void IWineD3DBaseTextureImpl_CleanUp(IWineD3DBaseTexture *iface) { void IWineD3DBaseTextureImpl_CleanUp(IWineD3DBaseTexture *iface) {
IWineD3DBaseTextureImpl *This = (IWineD3DBaseTextureImpl *)iface; IWineD3DBaseTextureImpl *This = (IWineD3DBaseTextureImpl *)iface;
IWineD3DDeviceImpl *device = This->resource.wineD3DDevice;
TRACE("(%p) : textureName(%d)\n", This, This->baseTexture.textureName); TRACE("(%p) : textureName(%d)\n", This, This->baseTexture.textureName);
if (This->baseTexture.textureName != 0) { if (This->baseTexture.textureName != 0) {
ENTER_GL(); ENTER_GL();
ActivateContext(device, device->lastActiveRenderTarget, CTXUSAGE_RESOURCELOAD);
TRACE("(%p) : Deleting texture %d\n", This, This->baseTexture.textureName); TRACE("(%p) : Deleting texture %d\n", This, This->baseTexture.textureName);
glDeleteTextures(1, &This->baseTexture.textureName); glDeleteTextures(1, &This->baseTexture.textureName);
LEAVE_GL(); LEAVE_GL();
...@@ -236,7 +239,6 @@ HRESULT WINAPI IWineD3DBaseTextureImpl_BindTexture(IWineD3DBaseTexture *iface) { ...@@ -236,7 +239,6 @@ HRESULT WINAPI IWineD3DBaseTextureImpl_BindTexture(IWineD3DBaseTexture *iface) {
textureDimensions = IWineD3DBaseTexture_GetTextureDimensions(iface); textureDimensions = IWineD3DBaseTexture_GetTextureDimensions(iface);
ENTER_GL(); ENTER_GL();
/* Generate a texture name if we don't already have one */ /* Generate a texture name if we don't already have one */
if (This->baseTexture.textureName == 0) { if (This->baseTexture.textureName == 0) {
glGenTextures(1, &This->baseTexture.textureName); glGenTextures(1, &This->baseTexture.textureName);
......
...@@ -706,6 +706,14 @@ void ActivateContext(IWineD3DDeviceImpl *This, IWineD3DSurface *target, ContextU ...@@ -706,6 +706,14 @@ void ActivateContext(IWineD3DDeviceImpl *This, IWineD3DSurface *target, ContextU
} }
} }
if (readTexture) { if (readTexture) {
BOOL oldInDraw = This->isInDraw;
/* PreLoad requires a context to load the texture, thus it will call ActivateContext.
* Set the isInDraw to true to signal PreLoad that it has a context. Will be tricky
* when using offscreen rendering with multithreading
*/
This->isInDraw = TRUE;
/* Do that before switching the context: /* Do that before switching the context:
* Read the back buffer of the old drawable into the destination texture * Read the back buffer of the old drawable into the destination texture
*/ */
...@@ -713,6 +721,8 @@ void ActivateContext(IWineD3DDeviceImpl *This, IWineD3DSurface *target, ContextU ...@@ -713,6 +721,8 @@ void ActivateContext(IWineD3DDeviceImpl *This, IWineD3DSurface *target, ContextU
/* Assume that the drawable will be modified by some other things now */ /* Assume that the drawable will be modified by some other things now */
((IWineD3DSurfaceImpl *) This->lastActiveRenderTarget)->Flags &= ~SFLAG_INDRAWABLE; ((IWineD3DSurfaceImpl *) This->lastActiveRenderTarget)->Flags &= ~SFLAG_INDRAWABLE;
This->isInDraw = oldInDraw;
} }
This->lastActiveRenderTarget = target; This->lastActiveRenderTarget = target;
if(oldRenderOffscreen != This->render_offscreen && This->depth_copy_state != WINED3D_DCS_NO_COPY) { if(oldRenderOffscreen != This->render_offscreen && This->depth_copy_state != WINED3D_DCS_NO_COPY) {
......
...@@ -104,11 +104,23 @@ static void WINAPI IWineD3DCubeTextureImpl_PreLoad(IWineD3DCubeTexture *iface) { ...@@ -104,11 +104,23 @@ static void WINAPI IWineD3DCubeTextureImpl_PreLoad(IWineD3DCubeTexture *iface) {
unsigned int i,j; unsigned int i,j;
BOOL setGlTextureDesc = FALSE; BOOL setGlTextureDesc = FALSE;
IWineD3DCubeTextureImpl *This = (IWineD3DCubeTextureImpl *)iface; IWineD3DCubeTextureImpl *This = (IWineD3DCubeTextureImpl *)iface;
IWineD3DDeviceImpl *device = This->resource.wineD3DDevice;
TRACE("(%p) : About to load texture: dirtified(%d)\n", This, This->baseTexture.dirty); TRACE("(%p) : About to load texture: dirtified(%d)\n", This, This->baseTexture.dirty);
if (This->baseTexture.textureName == 0) setGlTextureDesc = TRUE; if (This->baseTexture.textureName == 0) setGlTextureDesc = TRUE;
/* We only have to activate a context for gl when we're not drawing. In most cases PreLoad will be called during draw
* and a context was activated at the beginning of drawPrimitive
*/
if(!device->isInDraw) {
/* No danger of recursive calls, ActivateContext sets isInDraw to true when loading
* offscreen render targets into their texture
*/
ENTER_GL();
ActivateContext(device, device->lastActiveRenderTarget, CTXUSAGE_RESOURCELOAD);
LEAVE_GL();
}
IWineD3DCubeTexture_BindTexture(iface); IWineD3DCubeTexture_BindTexture(iface);
ENTER_GL(); ENTER_GL();
......
...@@ -250,6 +250,9 @@ static void CreateVBO(IWineD3DVertexBufferImpl *object) { ...@@ -250,6 +250,9 @@ static void CreateVBO(IWineD3DVertexBufferImpl *object) {
TRACE("Creating an OpenGL vertex buffer object for IWineD3DVertexBuffer %p Usage(%s)\n", object, debug_d3dusage(vboUsage)); TRACE("Creating an OpenGL vertex buffer object for IWineD3DVertexBuffer %p Usage(%s)\n", object, debug_d3dusage(vboUsage));
ENTER_GL(); ENTER_GL();
/* Make sure that a context is there. Needed in a multithreaded environment. Otherwise this call is a nop */
ActivateContext(This, This->lastActiveRenderTarget, CTXUSAGE_RESOURCELOAD);
/* Make sure that the gl error is cleared. Do not use checkGLcall /* Make sure that the gl error is cleared. Do not use checkGLcall
* here because checkGLcall just prints a fixme and continues. However, * here because checkGLcall just prints a fixme and continues. However,
* if an error during VBO creation occurs we can fall back to non-vbo operation * if an error during VBO creation occurs we can fall back to non-vbo operation
...@@ -377,6 +380,9 @@ static void CreateIndexBufferVBO(IWineD3DDeviceImpl *This, IWineD3DIndexBufferIm ...@@ -377,6 +380,9 @@ static void CreateIndexBufferVBO(IWineD3DDeviceImpl *This, IWineD3DIndexBufferIm
IWineD3DDeviceImpl_MarkStateDirty(This, STATE_INDEXBUFFER); IWineD3DDeviceImpl_MarkStateDirty(This, STATE_INDEXBUFFER);
ENTER_GL(); ENTER_GL();
/* Make sure that a context is there. Needed in a multithreaded environment. Otherwise this call is a nop */
ActivateContext(This, This->lastActiveRenderTarget, CTXUSAGE_RESOURCELOAD);
while(glGetError()); while(glGetError());
GL_EXTCALL(glGenBuffersARB(1, &object->vbo)); GL_EXTCALL(glGenBuffersARB(1, &object->vbo));
...@@ -1756,6 +1762,13 @@ static HRESULT WINAPI IWineD3DDeviceImpl_Uninit3D(IWineD3DDevice *iface, D3DCB_D ...@@ -1756,6 +1762,13 @@ static HRESULT WINAPI IWineD3DDeviceImpl_Uninit3D(IWineD3DDevice *iface, D3DCB_D
if(!This->d3d_initialized) return WINED3DERR_INVALIDCALL; if(!This->d3d_initialized) return WINED3DERR_INVALIDCALL;
ENTER_GL();
/* I don't think that the interface guarants that the device is destroyed from the same thread
* it was created. Thus make sure a context is active for the glDelete* calls
*/
ActivateContext(This, This->lastActiveRenderTarget, CTXUSAGE_RESOURCELOAD);
LEAVE_GL();
/* Delete the pbuffer context if there is any */ /* Delete the pbuffer context if there is any */
if(This->pbufferContext) DestroyContext(This, This->pbufferContext); if(This->pbufferContext) DestroyContext(This, This->pbufferContext);
...@@ -3674,6 +3687,16 @@ static HRESULT WINAPI IWineD3DDeviceImpl_ProcessVertices(IWineD3DDevice *iface, ...@@ -3674,6 +3687,16 @@ static HRESULT WINAPI IWineD3DDeviceImpl_ProcessVertices(IWineD3DDevice *iface,
WARN("NULL source vertex buffer\n"); WARN("NULL source vertex buffer\n");
return WINED3DERR_INVALIDCALL; return WINED3DERR_INVALIDCALL;
} }
/* Need any context to write to the vbo. In a non-multithreaded environment a context is there anyway,
* and this call is quite performance critical, so don't call needlessly
*/
if(This->createParms.BehaviorFlags & WINED3DCREATE_MULTITHREADED) {
ENTER_GL();
ActivateContext(This, This->lastActiveRenderTarget, CTXUSAGE_RESOURCELOAD);
LEAVE_GL();
}
/* We don't need the source vbo because this buffer is only used as /* We don't need the source vbo because this buffer is only used as
* a source for ProcessVertices. Avoid wasting resources by converting the * a source for ProcessVertices. Avoid wasting resources by converting the
* buffer and loading the VBO * buffer and loading the VBO
...@@ -4103,6 +4126,9 @@ static HRESULT WINAPI IWineD3DDeviceImpl_EndScene(IWineD3DDevice *iface) { ...@@ -4103,6 +4126,9 @@ static HRESULT WINAPI IWineD3DDeviceImpl_EndScene(IWineD3DDevice *iface) {
} }
ENTER_GL(); ENTER_GL();
if(This->createParms.BehaviorFlags & WINED3DCREATE_MULTITHREADED) {
ActivateContext(This, This->lastActiveRenderTarget, CTXUSAGE_RESOURCELOAD);
}
/* We only have to do this if we need to read the, swapbuffers performs a flush for us */ /* We only have to do this if we need to read the, swapbuffers performs a flush for us */
glFlush(); glFlush();
checkGLcall("glFlush"); checkGLcall("glFlush");
...@@ -4152,6 +4178,10 @@ static HRESULT WINAPI IWineD3DDeviceImpl_Clear(IWineD3DDevice *iface, DWORD Coun ...@@ -4152,6 +4178,10 @@ static HRESULT WINAPI IWineD3DDeviceImpl_Clear(IWineD3DDevice *iface, DWORD Coun
} }
ENTER_GL(); ENTER_GL();
/* This is for offscreen rendering as well as for multithreading, thus activate the set render target
* and not the last active one.
*/
ActivateContext(This, This->render_targets[0], CTXUSAGE_RESOURCELOAD);
glEnable(GL_SCISSOR_TEST); glEnable(GL_SCISSOR_TEST);
checkGLcall("glEnable GL_SCISSOR_TEST"); checkGLcall("glEnable GL_SCISSOR_TEST");
...@@ -4755,6 +4785,9 @@ static HRESULT WINAPI IWineD3DDeviceImpl_UpdateSurface(IWineD3DDevice *iface, ...@@ -4755,6 +4785,9 @@ static HRESULT WINAPI IWineD3DDeviceImpl_UpdateSurface(IWineD3DDevice *iface,
} }
ENTER_GL(); ENTER_GL();
ActivateContext(This, This->lastActiveRenderTarget, CTXUSAGE_RESOURCELOAD);
if (GL_SUPPORT(ARB_MULTITEXTURE)) { if (GL_SUPPORT(ARB_MULTITEXTURE)) {
GL_EXTCALL(glActiveTextureARB(GL_TEXTURE0_ARB)); GL_EXTCALL(glActiveTextureARB(GL_TEXTURE0_ARB));
checkGLcall("glActiveTextureARB"); checkGLcall("glActiveTextureARB");
...@@ -4995,6 +5028,10 @@ static HRESULT WINAPI IWineD3DDeviceImpl_SetFrontBackBuffers(IWineD3DDevice *ifa ...@@ -4995,6 +5028,10 @@ static HRESULT WINAPI IWineD3DDeviceImpl_SetFrontBackBuffers(IWineD3DDevice *ifa
if(Swapchain->backBuffer[0] != Back) { if(Swapchain->backBuffer[0] != Back) {
TRACE("Changing the back buffer from %p to %p\n", Swapchain->backBuffer, Back); TRACE("Changing the back buffer from %p to %p\n", Swapchain->backBuffer, Back);
/* What to do about the context here in the case of multithreading? Not sure.
* This function is called by IDirect3D7::CreateDevice so in theory its initialization code
*/
ENTER_GL(); ENTER_GL();
if(!Swapchain->backBuffer[0]) { if(!Swapchain->backBuffer[0]) {
/* GL was told to draw to the front buffer at creation, /* GL was told to draw to the front buffer at creation,
...@@ -5248,6 +5285,7 @@ static HRESULT WINAPI IWineD3DDeviceImpl_SetCursorProperties(IWineD3DDevice* i ...@@ -5248,6 +5285,7 @@ static HRESULT WINAPI IWineD3DDeviceImpl_SetCursorProperties(IWineD3DDevice* i
/* some basic validation checks */ /* some basic validation checks */
if(This->cursorTexture) { if(This->cursorTexture) {
ENTER_GL(); ENTER_GL();
ActivateContext(This, This->lastActiveRenderTarget, CTXUSAGE_RESOURCELOAD);
glDeleteTextures(1, &This->cursorTexture); glDeleteTextures(1, &This->cursorTexture);
LEAVE_GL(); LEAVE_GL();
This->cursorTexture = 0; This->cursorTexture = 0;
...@@ -5419,6 +5457,7 @@ static void updateSurfaceDesc(IWineD3DSurfaceImpl *surface, WINED3DPRESENT_PARAM ...@@ -5419,6 +5457,7 @@ static void updateSurfaceDesc(IWineD3DSurfaceImpl *surface, WINED3DPRESENT_PARAM
} }
if(surface->glDescription.textureName) { if(surface->glDescription.textureName) {
ENTER_GL(); ENTER_GL();
ActivateContext(This, This->lastActiveRenderTarget, CTXUSAGE_RESOURCELOAD);
glDeleteTextures(1, &surface->glDescription.textureName); glDeleteTextures(1, &surface->glDescription.textureName);
LEAVE_GL(); LEAVE_GL();
surface->glDescription.textureName = 0; surface->glDescription.textureName = 0;
......
...@@ -59,7 +59,10 @@ static ULONG WINAPI IWineD3DIndexBufferImpl_Release(IWineD3DIndexBuffer *iface) ...@@ -59,7 +59,10 @@ static ULONG WINAPI IWineD3DIndexBufferImpl_Release(IWineD3DIndexBuffer *iface)
TRACE("(%p) : Releasing from %d\n", This, ref + 1); TRACE("(%p) : Releasing from %d\n", This, ref + 1);
if (ref == 0) { if (ref == 0) {
if(This->vbo) { if(This->vbo) {
IWineD3DDeviceImpl *device = This->resource.wineD3DDevice;
ENTER_GL(); ENTER_GL();
ActivateContext(device, device->lastActiveRenderTarget, CTXUSAGE_RESOURCELOAD);
/* No need to manually unset the buffer. glDeleteBuffers unsets it for the current context, /* No need to manually unset the buffer. glDeleteBuffers unsets it for the current context,
* but not for other contexts. However, because the d3d buffer is destroyed the app has to * but not for other contexts. However, because the d3d buffer is destroyed the app has to
* unset it before doing the next draw, thus dirtifying the index buffer state and forcing * unset it before doing the next draw, thus dirtifying the index buffer state and forcing
...@@ -153,7 +156,13 @@ static HRESULT WINAPI IWineD3DIndexBufferImpl_Unlock(IWineD3DIndexBuffer *iface) ...@@ -153,7 +156,13 @@ static HRESULT WINAPI IWineD3DIndexBufferImpl_Unlock(IWineD3DIndexBuffer *iface)
/* For now load in unlock */ /* For now load in unlock */
if(locks == 0 && This->vbo) { if(locks == 0 && This->vbo) {
IWineD3DDeviceImpl *device = This->resource.wineD3DDevice;
ENTER_GL(); ENTER_GL();
if(device->createParms.BehaviorFlags & WINED3DCREATE_MULTITHREADED) {
ActivateContext(device, device->lastActiveRenderTarget, CTXUSAGE_RESOURCELOAD);
}
GL_EXTCALL(glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, This->vbo)); GL_EXTCALL(glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, This->vbo));
checkGLcall("glBindBufferARB"); checkGLcall("glBindBufferARB");
GL_EXTCALL(glBufferSubDataARB(GL_ELEMENT_ARRAY_BUFFER_ARB, GL_EXTCALL(glBufferSubDataARB(GL_ELEMENT_ARRAY_BUFFER_ARB,
...@@ -163,7 +172,7 @@ static HRESULT WINAPI IWineD3DIndexBufferImpl_Unlock(IWineD3DIndexBuffer *iface) ...@@ -163,7 +172,7 @@ static HRESULT WINAPI IWineD3DIndexBufferImpl_Unlock(IWineD3DIndexBuffer *iface)
This->dirtystart = 0; This->dirtystart = 0;
This->dirtyend = 0; This->dirtyend = 0;
/* TODO: Move loading into preload when the buffer is used, that avoids dirtifying the state */ /* TODO: Move loading into preload when the buffer is used, that avoids dirtifying the state */
IWineD3DDeviceImpl_MarkStateDirty(This->resource.wineD3DDevice, STATE_INDEXBUFFER); IWineD3DDeviceImpl_MarkStateDirty(device, STATE_INDEXBUFFER);
} }
return WINED3D_OK; return WINED3D_OK;
} }
......
...@@ -60,12 +60,8 @@ static void surface_download_data(IWineD3DSurfaceImpl *This) { ...@@ -60,12 +60,8 @@ static void surface_download_data(IWineD3DSurfaceImpl *This) {
TRACE("(%p) : Calling glGetCompressedTexImageARB level %d, format %#x, type %#x, data %p\n", This, This->glDescription.level, TRACE("(%p) : Calling glGetCompressedTexImageARB level %d, format %#x, type %#x, data %p\n", This, This->glDescription.level,
This->glDescription.glFormat, This->glDescription.glType, This->resource.allocatedMemory); This->glDescription.glFormat, This->glDescription.glType, This->resource.allocatedMemory);
ENTER_GL();
GL_EXTCALL(glGetCompressedTexImageARB(This->glDescription.target, This->glDescription.level, This->resource.allocatedMemory)); GL_EXTCALL(glGetCompressedTexImageARB(This->glDescription.target, This->glDescription.level, This->resource.allocatedMemory));
checkGLcall("glGetCompressedTexImageARB()"); checkGLcall("glGetCompressedTexImageARB()");
LEAVE_GL();
} }
} else { } else {
void *mem; void *mem;
...@@ -89,14 +85,10 @@ static void surface_download_data(IWineD3DSurfaceImpl *This) { ...@@ -89,14 +85,10 @@ static void surface_download_data(IWineD3DSurfaceImpl *This) {
TRACE("(%p) : Calling glGetTexImage level %d, format %#x, type %#x, data %p\n", This, This->glDescription.level, TRACE("(%p) : Calling glGetTexImage level %d, format %#x, type %#x, data %p\n", This, This->glDescription.level,
This->glDescription.glFormat, This->glDescription.glType, mem); This->glDescription.glFormat, This->glDescription.glType, mem);
ENTER_GL();
glGetTexImage(This->glDescription.target, This->glDescription.level, This->glDescription.glFormat, glGetTexImage(This->glDescription.target, This->glDescription.level, This->glDescription.glFormat,
This->glDescription.glType, mem); This->glDescription.glType, mem);
checkGLcall("glGetTexImage()"); checkGLcall("glGetTexImage()");
LEAVE_GL();
if (This->Flags & SFLAG_NONPOW2) { if (This->Flags & SFLAG_NONPOW2) {
LPBYTE src_data, dst_data; LPBYTE src_data, dst_data;
int y; int y;
...@@ -258,6 +250,7 @@ ULONG WINAPI IWineD3DSurfaceImpl_Release(IWineD3DSurface *iface) { ...@@ -258,6 +250,7 @@ ULONG WINAPI IWineD3DSurfaceImpl_Release(IWineD3DSurface *iface) {
* and the lastActiveRenderTarget member shouldn't matter * and the lastActiveRenderTarget member shouldn't matter
*/ */
if(swapchain) { if(swapchain) {
ENTER_GL(); /* For ActivateContext */
if(swapchain->backBuffer && swapchain->backBuffer[0] != iface) { if(swapchain->backBuffer && swapchain->backBuffer[0] != iface) {
TRACE("Activating primary back buffer\n"); TRACE("Activating primary back buffer\n");
ActivateContext(device, swapchain->backBuffer[0], CTXUSAGE_RESOURCELOAD); ActivateContext(device, swapchain->backBuffer[0], CTXUSAGE_RESOURCELOAD);
...@@ -272,6 +265,7 @@ ULONG WINAPI IWineD3DSurfaceImpl_Release(IWineD3DSurface *iface) { ...@@ -272,6 +265,7 @@ ULONG WINAPI IWineD3DSurfaceImpl_Release(IWineD3DSurface *iface) {
*/ */
device->lastActiveRenderTarget = (IWineD3DSurface *) 0xdeadbabe; device->lastActiveRenderTarget = (IWineD3DSurface *) 0xdeadbabe;
} }
LEAVE_GL();
} else { } else {
/* May happen during ddraw uninitialization */ /* May happen during ddraw uninitialization */
TRACE("Render target set, but swapchain does not exist!\n"); TRACE("Render target set, but swapchain does not exist!\n");
...@@ -281,6 +275,15 @@ ULONG WINAPI IWineD3DSurfaceImpl_Release(IWineD3DSurface *iface) { ...@@ -281,6 +275,15 @@ ULONG WINAPI IWineD3DSurfaceImpl_Release(IWineD3DSurface *iface) {
if (This->glDescription.textureName != 0) { /* release the openGL texture.. */ if (This->glDescription.textureName != 0) { /* release the openGL texture.. */
ENTER_GL(); ENTER_GL();
/* Need a context to destroy the texture. Use the currently active render target, but only if
* the primary render target exists. Otherwise lastActiveRenderTarget is garbage, see above.
* When destroying the primary rt, Uninit3D will activate a context before doing anything
*/
if(device->render_targets[0]) {
ActivateContext(device, device->lastActiveRenderTarget, CTXUSAGE_RESOURCELOAD);
}
TRACE("Deleting texture %d\n", This->glDescription.textureName); TRACE("Deleting texture %d\n", This->glDescription.textureName);
glDeleteTextures(1, &This->glDescription.textureName); glDeleteTextures(1, &This->glDescription.textureName);
LEAVE_GL(); LEAVE_GL();
...@@ -338,13 +341,11 @@ DWORD WINAPI IWineD3DSurfaceImpl_GetPriority(IWineD3DSurface *iface) { ...@@ -338,13 +341,11 @@ DWORD WINAPI IWineD3DSurfaceImpl_GetPriority(IWineD3DSurface *iface) {
} }
void WINAPI IWineD3DSurfaceImpl_PreLoad(IWineD3DSurface *iface) { void WINAPI IWineD3DSurfaceImpl_PreLoad(IWineD3DSurface *iface) {
/* TODO: re-write the way textures and managed,
* use a 'opengl context manager' to manage RenderTarget surfaces
** *********************************************************/
/* TODO: check for locks */ /* TODO: check for locks */
IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *)iface; IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *)iface;
IWineD3DBaseTexture *baseTexture = NULL; IWineD3DBaseTexture *baseTexture = NULL;
IWineD3DDeviceImpl *device = This->resource.wineD3DDevice;
TRACE("(%p)Checking to see if the container is a base texture\n", This); TRACE("(%p)Checking to see if the container is a base texture\n", This);
if (IWineD3DSurface_GetContainer(iface, &IID_IWineD3DBaseTexture, (void **)&baseTexture) == WINED3D_OK) { if (IWineD3DSurface_GetContainer(iface, &IID_IWineD3DBaseTexture, (void **)&baseTexture) == WINED3D_OK) {
TRACE("Passing to conatiner\n"); TRACE("Passing to conatiner\n");
...@@ -352,10 +353,12 @@ void WINAPI IWineD3DSurfaceImpl_PreLoad(IWineD3DSurface *iface) { ...@@ -352,10 +353,12 @@ void WINAPI IWineD3DSurfaceImpl_PreLoad(IWineD3DSurface *iface) {
IWineD3DBaseTexture_Release(baseTexture); IWineD3DBaseTexture_Release(baseTexture);
} else { } else {
TRACE("(%p) : About to load surface\n", This); TRACE("(%p) : About to load surface\n", This);
ENTER_GL(); ENTER_GL();
#if 0 /* TODO: context manager support */ if(!device->isInDraw) {
IWineD3DContextManager_PushState(This->contextManager, GL_TEXTURE_2D, ENABLED, NOW /* make sure the state is applied now */); ActivateContext(device, device->lastActiveRenderTarget, CTXUSAGE_RESOURCELOAD);
#endif }
glEnable(This->glDescription.target);/* make sure texture support is enabled in this context */ glEnable(This->glDescription.target);/* make sure texture support is enabled in this context */
if (!This->glDescription.level) { if (!This->glDescription.level) {
if (!This->glDescription.textureName) { if (!This->glDescription.textureName) {
...@@ -377,11 +380,6 @@ void WINAPI IWineD3DSurfaceImpl_PreLoad(IWineD3DSurface *iface) { ...@@ -377,11 +380,6 @@ void WINAPI IWineD3DSurfaceImpl_PreLoad(IWineD3DSurface *iface) {
tmp = 0.9f; tmp = 0.9f;
glPrioritizeTextures(1, &This->glDescription.textureName, &tmp); glPrioritizeTextures(1, &This->glDescription.textureName, &tmp);
} }
/* TODO: disable texture support, if it wastn't enabled when we entered. */
#if 0 /* TODO: context manager support */
IWineD3DContextManager_PopState(This->contextManager, GL_TEXTURE_2D, DISABLED,DELAYED
/* we don't care when the state is disabled(if atall) */);
#endif
LEAVE_GL(); LEAVE_GL();
} }
return; return;
...@@ -768,24 +766,25 @@ static HRESULT WINAPI IWineD3DSurfaceImpl_LockRect(IWineD3DSurface *iface, WINED ...@@ -768,24 +766,25 @@ static HRESULT WINAPI IWineD3DSurfaceImpl_LockRect(IWineD3DSurface *iface, WINED
/* This path is for normal surfaces, offscreen render targets and everything else that is in a gl texture */ /* This path is for normal surfaces, offscreen render targets and everything else that is in a gl texture */
TRACE("locking an ordinarary surface\n"); TRACE("locking an ordinarary surface\n");
/* TODO: Make sure that *any* context is active for this thread. It is not important which context that is,
* nor that is has any special setup(CTXUSAGE_LOADRESOURCE is fine), but the code below needs a context.
* A context is guaranteed to be there in a single threaded environment, but not with multithreading
*/
if (0 != This->glDescription.textureName) { if (0 != This->glDescription.textureName) {
/* Now I have to copy thing bits back */ /* Now I have to copy thing bits back */
ENTER_GL();
if(myDevice->createParms.BehaviorFlags & WINED3DCREATE_MULTITHREADED) {
ActivateContext(myDevice, myDevice->lastActiveRenderTarget, CTXUSAGE_RESOURCELOAD);
}
/* Make sure that a proper texture unit is selected, bind the texture and dirtify the sampler to restore the texture on the next draw */ /* Make sure that a proper texture unit is selected, bind the texture and dirtify the sampler to restore the texture on the next draw */
if (GL_SUPPORT(ARB_MULTITEXTURE)) { if (GL_SUPPORT(ARB_MULTITEXTURE)) {
ENTER_GL();
GL_EXTCALL(glActiveTextureARB(GL_TEXTURE0_ARB)); GL_EXTCALL(glActiveTextureARB(GL_TEXTURE0_ARB));
checkGLcall("glActiveTextureARB"); checkGLcall("glActiveTextureARB");
LEAVE_GL();
} }
IWineD3DDeviceImpl_MarkStateDirty(This->resource.wineD3DDevice, STATE_SAMPLER(0)); IWineD3DDeviceImpl_MarkStateDirty(This->resource.wineD3DDevice, STATE_SAMPLER(0));
IWineD3DSurface_PreLoad(iface); IWineD3DSurface_PreLoad(iface);
surface_download_data(This); surface_download_data(This);
LEAVE_GL();
} }
/* The local copy is now up to date to the opengl one because a full download was done */ /* The local copy is now up to date to the opengl one because a full download was done */
......
...@@ -146,6 +146,8 @@ static HRESULT WINAPI IWineD3DSwapChainImpl_Present(IWineD3DSwapChain *iface, CO ...@@ -146,6 +146,8 @@ static HRESULT WINAPI IWineD3DSwapChainImpl_Present(IWineD3DSwapChain *iface, CO
ENTER_GL(); ENTER_GL();
/* Does glXSwapBuffers need a glx context? I don't think so. Blt will activate its own context if needed */
/* Render the cursor onto the back buffer, using our nifty directdraw blitting code :-) */ /* Render the cursor onto the back buffer, using our nifty directdraw blitting code :-) */
if(This->wineD3DDevice->bCursorVisible && This->wineD3DDevice->cursorTexture) { if(This->wineD3DDevice->bCursorVisible && This->wineD3DDevice->cursorTexture) {
IWineD3DSurfaceImpl cursor; IWineD3DSurfaceImpl cursor;
......
...@@ -97,11 +97,21 @@ static void WINAPI IWineD3DTextureImpl_PreLoad(IWineD3DTexture *iface) { ...@@ -97,11 +97,21 @@ static void WINAPI IWineD3DTextureImpl_PreLoad(IWineD3DTexture *iface) {
unsigned int i; unsigned int i;
BOOL setGlTextureDesc = FALSE; BOOL setGlTextureDesc = FALSE;
IWineD3DTextureImpl *This = (IWineD3DTextureImpl *)iface; IWineD3DTextureImpl *This = (IWineD3DTextureImpl *)iface;
IWineD3DDeviceImpl *device = This->resource.wineD3DDevice;
TRACE("(%p) : About to load texture\n", This); TRACE("(%p) : About to load texture\n", This);
if (This->baseTexture.textureName == 0) setGlTextureDesc = TRUE; if (This->baseTexture.textureName == 0) setGlTextureDesc = TRUE;
if(!device->isInDraw) {
/* ActivateContext sets isInDraw to TRUE when loading a pbuffer into a texture, thus no danger of
* recursive calls
*/
ENTER_GL();
ActivateContext(device, device->lastActiveRenderTarget, CTXUSAGE_RESOURCELOAD);
LEAVE_GL();
}
IWineD3DTexture_BindTexture(iface); IWineD3DTexture_BindTexture(iface);
ENTER_GL(); ENTER_GL();
/* If were dirty then reload the surfaces */ /* If were dirty then reload the surfaces */
......
...@@ -810,7 +810,8 @@ void set_tex_op_nvrc(IWineD3DDevice *iface, BOOL is_alpha, int stage, WINED3DTEX ...@@ -810,7 +810,8 @@ void set_tex_op_nvrc(IWineD3DDevice *iface, BOOL is_alpha, int stage, WINED3DTEX
get_src_and_opr_nvrc(stage, arg3, is_alpha, &tex_op_args.input[2], get_src_and_opr_nvrc(stage, arg3, is_alpha, &tex_op_args.input[2],
&tex_op_args.mapping[2], &tex_op_args.component_usage[2], texture_idx); &tex_op_args.mapping[2], &tex_op_args.component_usage[2], texture_idx);
ENTER_GL();
/* This is called by a state handler which has the gl lock held and a context for the thread */
switch(op) switch(op)
{ {
...@@ -1082,7 +1083,6 @@ void set_tex_op_nvrc(IWineD3DDevice *iface, BOOL is_alpha, int stage, WINED3DTEX ...@@ -1082,7 +1083,6 @@ void set_tex_op_nvrc(IWineD3DDevice *iface, BOOL is_alpha, int stage, WINED3DTEX
checkGLcall("set_tex_op_nvrc()\n"); checkGLcall("set_tex_op_nvrc()\n");
LEAVE_GL();
} }
static void get_src_and_opr(DWORD arg, BOOL is_alpha, GLenum* source, GLenum* operand) { static void get_src_and_opr(DWORD arg, BOOL is_alpha, GLenum* source, GLenum* operand) {
...@@ -1160,7 +1160,7 @@ void set_tex_op(IWineD3DDevice *iface, BOOL isAlpha, int Stage, WINED3DTEXTUREOP ...@@ -1160,7 +1160,7 @@ void set_tex_op(IWineD3DDevice *iface, BOOL isAlpha, int Stage, WINED3DTEXTUREOP
TRACE("Alpha?(%d), Stage:%d Op(%s), a1(%d), a2(%d), a3(%d)\n", isAlpha, Stage, debug_d3dtop(op), arg1, arg2, arg3); TRACE("Alpha?(%d), Stage:%d Op(%s), a1(%d), a2(%d), a3(%d)\n", isAlpha, Stage, debug_d3dtop(op), arg1, arg2, arg3);
ENTER_GL(); /* This is called by a state handler which has the gl lock held and a context for the thread */
/* Note: Operations usually involve two ars, src0 and src1 and are operations of /* Note: Operations usually involve two ars, src0 and src1 and are operations of
the form (a1 <operation> a2). However, some of the more complex operations the form (a1 <operation> a2). However, some of the more complex operations
...@@ -1681,7 +1681,6 @@ void set_tex_op(IWineD3DDevice *iface, BOOL isAlpha, int Stage, WINED3DTEXTUREOP ...@@ -1681,7 +1681,6 @@ void set_tex_op(IWineD3DDevice *iface, BOOL isAlpha, int Stage, WINED3DTEXTUREOP
glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE4_NV); glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE4_NV);
checkGLcall("GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE4_NV"); checkGLcall("GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE4_NV");
LEAVE_GL();
return; return;
} }
} /* GL_NV_texture_env_combine4 */ } /* GL_NV_texture_env_combine4 */
...@@ -2148,7 +2147,6 @@ void set_tex_op(IWineD3DDevice *iface, BOOL isAlpha, int Stage, WINED3DTEXTUREOP ...@@ -2148,7 +2147,6 @@ void set_tex_op(IWineD3DDevice *iface, BOOL isAlpha, int Stage, WINED3DTEXTUREOP
break; break;
default: default:
FIXME("Can't use COMBINE4 and COMBINE together, thisop=%s, otherop=%s, isAlpha(%d)\n", debug_d3dtop(op), debug_d3dtop(op2), isAlpha); FIXME("Can't use COMBINE4 and COMBINE together, thisop=%s, otherop=%s, isAlpha(%d)\n", debug_d3dtop(op), debug_d3dtop(op2), isAlpha);
LEAVE_GL();
return; return;
} }
} }
...@@ -2158,13 +2156,10 @@ void set_tex_op(IWineD3DDevice *iface, BOOL isAlpha, int Stage, WINED3DTEXTUREOP ...@@ -2158,13 +2156,10 @@ void set_tex_op(IWineD3DDevice *iface, BOOL isAlpha, int Stage, WINED3DTEXTUREOP
glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, useext(GL_COMBINE)); glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, useext(GL_COMBINE));
checkGLcall("GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, useext(GL_COMBINE)"); checkGLcall("GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, useext(GL_COMBINE)");
LEAVE_GL();
return; return;
} }
} }
LEAVE_GL();
/* After all the extensions, if still unhandled, report fixme */ /* After all the extensions, if still unhandled, report fixme */
FIXME("Unhandled texture operation %s\n", debug_d3dtop(op)); FIXME("Unhandled texture operation %s\n", debug_d3dtop(op));
#undef GLINFO_LOCATION #undef GLINFO_LOCATION
......
...@@ -62,7 +62,10 @@ static ULONG WINAPI IWineD3DVertexBufferImpl_Release(IWineD3DVertexBuffer *iface ...@@ -62,7 +62,10 @@ static ULONG WINAPI IWineD3DVertexBufferImpl_Release(IWineD3DVertexBuffer *iface
if (ref == 0) { if (ref == 0) {
if(This->vbo) { if(This->vbo) {
IWineD3DDeviceImpl *device = This->resource.wineD3DDevice;
ENTER_GL(); ENTER_GL();
ActivateContext(device, device->lastActiveRenderTarget, CTXUSAGE_RESOURCELOAD);
GL_EXTCALL(glDeleteBuffersARB(1, &This->vbo)); GL_EXTCALL(glDeleteBuffersARB(1, &This->vbo));
checkGLcall("glDeleteBuffersARB"); checkGLcall("glDeleteBuffersARB");
LEAVE_GL(); LEAVE_GL();
...@@ -244,6 +247,7 @@ inline BOOL WINAPI IWineD3DVertexBufferImpl_FindDecl(IWineD3DVertexBufferImpl *T ...@@ -244,6 +247,7 @@ inline BOOL WINAPI IWineD3DVertexBufferImpl_FindDecl(IWineD3DVertexBufferImpl *T
static void WINAPI IWineD3DVertexBufferImpl_PreLoad(IWineD3DVertexBuffer *iface) { static void WINAPI IWineD3DVertexBufferImpl_PreLoad(IWineD3DVertexBuffer *iface) {
IWineD3DVertexBufferImpl *This = (IWineD3DVertexBufferImpl *) iface; IWineD3DVertexBufferImpl *This = (IWineD3DVertexBufferImpl *) iface;
IWineD3DDeviceImpl *device = This->resource.wineD3DDevice;
BYTE *data; BYTE *data;
UINT start = 0, end = 0, stride = 0; UINT start = 0, end = 0, stride = 0;
BOOL declChanged = FALSE; BOOL declChanged = FALSE;
...@@ -259,7 +263,7 @@ static void WINAPI IWineD3DVertexBufferImpl_PreLoad(IWineD3DVertexBuffer *if ...@@ -259,7 +263,7 @@ static void WINAPI IWineD3DVertexBufferImpl_PreLoad(IWineD3DVertexBuffer *if
} }
/* Reading the declaration makes only sense if the stateblock is finalized and the buffer bound to a stream */ /* Reading the declaration makes only sense if the stateblock is finalized and the buffer bound to a stream */
if(This->resource.wineD3DDevice->isInDraw && This->bindCount > 0) { if(device->isInDraw && This->bindCount > 0) {
declChanged = IWineD3DVertexBufferImpl_FindDecl(This); declChanged = IWineD3DVertexBufferImpl_FindDecl(This);
} else if(This->Flags & VBFLAG_HASDESC) { } else if(This->Flags & VBFLAG_HASDESC) {
/* Reuse the declaration stored in the buffer. It will most likely not change, and if it does /* Reuse the declaration stored in the buffer. It will most likely not change, and if it does
...@@ -284,6 +288,7 @@ static void WINAPI IWineD3DVertexBufferImpl_PreLoad(IWineD3DVertexBuffer *if ...@@ -284,6 +288,7 @@ static void WINAPI IWineD3DVertexBufferImpl_PreLoad(IWineD3DVertexBuffer *if
if(This->declChanges > VB_MAXDECLCHANGES) { if(This->declChanges > VB_MAXDECLCHANGES) {
FIXME("Too much declaration changes, stopping converting\n"); FIXME("Too much declaration changes, stopping converting\n");
ENTER_GL(); ENTER_GL();
ActivateContext(device, device->lastActiveRenderTarget, CTXUSAGE_RESOURCELOAD);
GL_EXTCALL(glDeleteBuffersARB(1, &This->vbo)); GL_EXTCALL(glDeleteBuffersARB(1, &This->vbo));
checkGLcall("glDeleteBuffersARB"); checkGLcall("glDeleteBuffersARB");
LEAVE_GL(); LEAVE_GL();
...@@ -294,7 +299,7 @@ static void WINAPI IWineD3DVertexBufferImpl_PreLoad(IWineD3DVertexBuffer *if ...@@ -294,7 +299,7 @@ static void WINAPI IWineD3DVertexBufferImpl_PreLoad(IWineD3DVertexBuffer *if
* to force a reload. This happens only once per changed vertexbuffer and should occur rather * to force a reload. This happens only once per changed vertexbuffer and should occur rather
* rarely * rarely
*/ */
IWineD3DDeviceImpl_MarkStateDirty(This->resource.wineD3DDevice, STATE_STREAMSRC); IWineD3DDeviceImpl_MarkStateDirty(device, STATE_STREAMSRC);
return; return;
} }
...@@ -337,6 +342,9 @@ static void WINAPI IWineD3DVertexBufferImpl_PreLoad(IWineD3DVertexBuffer *if ...@@ -337,6 +342,9 @@ static void WINAPI IWineD3DVertexBufferImpl_PreLoad(IWineD3DVertexBuffer *if
TRACE("No conversion needed, locking directly into the VBO in future\n"); TRACE("No conversion needed, locking directly into the VBO in future\n");
ENTER_GL(); ENTER_GL();
if(!device->isInDraw) {
ActivateContext(device, device->lastActiveRenderTarget, CTXUSAGE_RESOURCELOAD);
}
GL_EXTCALL(glBindBufferARB(GL_ARRAY_BUFFER_ARB, This->vbo)); GL_EXTCALL(glBindBufferARB(GL_ARRAY_BUFFER_ARB, This->vbo));
checkGLcall("glBindBufferARB"); checkGLcall("glBindBufferARB");
GL_EXTCALL(glBufferSubDataARB(GL_ARRAY_BUFFER_ARB, start, end-start, This->resource.allocatedMemory + start)); GL_EXTCALL(glBufferSubDataARB(GL_ARRAY_BUFFER_ARB, start, end-start, This->resource.allocatedMemory + start));
...@@ -367,6 +375,9 @@ static void WINAPI IWineD3DVertexBufferImpl_PreLoad(IWineD3DVertexBuffer *if ...@@ -367,6 +375,9 @@ static void WINAPI IWineD3DVertexBufferImpl_PreLoad(IWineD3DVertexBuffer *if
This->strided.u.s.specular.dwType == WINED3DDECLTYPE_SHORT4 || This->strided.u.s.specular.dwType == WINED3DDECLTYPE_D3DCOLOR); This->strided.u.s.specular.dwType == WINED3DDECLTYPE_SHORT4 || This->strided.u.s.specular.dwType == WINED3DDECLTYPE_D3DCOLOR);
ENTER_GL(); ENTER_GL();
if(!device->isInDraw) {
ActivateContext(device, device->lastActiveRenderTarget, CTXUSAGE_RESOURCELOAD);
}
GL_EXTCALL(glBindBufferARB(GL_ARRAY_BUFFER_ARB, This->vbo)); GL_EXTCALL(glBindBufferARB(GL_ARRAY_BUFFER_ARB, This->vbo));
checkGLcall("glBindBufferARB"); checkGLcall("glBindBufferARB");
GL_EXTCALL(glBufferSubDataARB(GL_ARRAY_BUFFER_ARB, start, end - start, data)); GL_EXTCALL(glBufferSubDataARB(GL_ARRAY_BUFFER_ARB, start, end - start, data));
......
...@@ -94,12 +94,16 @@ static void WINAPI IWineD3DVolumeTextureImpl_PreLoad(IWineD3DVolumeTexture *ifac ...@@ -94,12 +94,16 @@ static void WINAPI IWineD3DVolumeTextureImpl_PreLoad(IWineD3DVolumeTexture *ifac
/* Overrider the IWineD3DResource Preload method */ /* Overrider the IWineD3DResource Preload method */
UINT i; UINT i;
IWineD3DVolumeTextureImpl *This = (IWineD3DVolumeTextureImpl *)iface; IWineD3DVolumeTextureImpl *This = (IWineD3DVolumeTextureImpl *)iface;
IWineD3DDeviceImpl *device = This->resource.wineD3DDevice;
TRACE("(%p) : About to load texture\n", This); TRACE("(%p) : About to load texture\n", This);
IWineD3DVolumeTexture_BindTexture(iface); IWineD3DVolumeTexture_BindTexture(iface);
ENTER_GL(); ENTER_GL();
if(!device->isInDraw) {
ActivateContext(device, device->lastActiveRenderTarget, CTXUSAGE_RESOURCELOAD);
}
/* If were dirty then reload the volumes */ /* If were dirty then reload the volumes */
if(This->baseTexture.dirty) { if(This->baseTexture.dirty) {
for (i = 0; i < This->baseTexture.levels; i++) { for (i = 0; i < This->baseTexture.levels; i++) {
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment