diff --git a/dlls/wined3d/basetexture.c b/dlls/wined3d/basetexture.c index c34b9c81365..d01847fe536 100644 --- a/dlls/wined3d/basetexture.c +++ b/dlls/wined3d/basetexture.c @@ -96,9 +96,12 @@ ULONG WINAPI IWineD3DBaseTextureImpl_Release(IWineD3DBaseTexture *iface) { /* class static */ void IWineD3DBaseTextureImpl_CleanUp(IWineD3DBaseTexture *iface) { IWineD3DBaseTextureImpl *This = (IWineD3DBaseTextureImpl *)iface; + IWineD3DDeviceImpl *device = This->resource.wineD3DDevice; + TRACE("(%p) : textureName(%d)\n", This, This->baseTexture.textureName); if (This->baseTexture.textureName != 0) { ENTER_GL(); + ActivateContext(device, device->lastActiveRenderTarget, CTXUSAGE_RESOURCELOAD); TRACE("(%p) : Deleting texture %d\n", This, This->baseTexture.textureName); glDeleteTextures(1, &This->baseTexture.textureName); LEAVE_GL(); @@ -236,7 +239,6 @@ HRESULT WINAPI IWineD3DBaseTextureImpl_BindTexture(IWineD3DBaseTexture *iface) { textureDimensions = IWineD3DBaseTexture_GetTextureDimensions(iface); ENTER_GL(); - /* Generate a texture name if we don't already have one */ if (This->baseTexture.textureName == 0) { glGenTextures(1, &This->baseTexture.textureName); diff --git a/dlls/wined3d/context.c b/dlls/wined3d/context.c index 5fe2b58258f..ead24ee93a8 100644 --- a/dlls/wined3d/context.c +++ b/dlls/wined3d/context.c @@ -706,6 +706,14 @@ void ActivateContext(IWineD3DDeviceImpl *This, IWineD3DSurface *target, ContextU } } 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: * Read the back buffer of the old drawable into the destination texture */ @@ -713,6 +721,8 @@ void ActivateContext(IWineD3DDeviceImpl *This, IWineD3DSurface *target, ContextU /* Assume that the drawable will be modified by some other things now */ ((IWineD3DSurfaceImpl *) This->lastActiveRenderTarget)->Flags &= ~SFLAG_INDRAWABLE; + + This->isInDraw = oldInDraw; } This->lastActiveRenderTarget = target; if(oldRenderOffscreen != This->render_offscreen && This->depth_copy_state != WINED3D_DCS_NO_COPY) { diff --git a/dlls/wined3d/cubetexture.c b/dlls/wined3d/cubetexture.c index f3df9f49091..d9b0c47e403 100644 --- a/dlls/wined3d/cubetexture.c +++ b/dlls/wined3d/cubetexture.c @@ -104,11 +104,23 @@ static void WINAPI IWineD3DCubeTextureImpl_PreLoad(IWineD3DCubeTexture *iface) { unsigned int i,j; BOOL setGlTextureDesc = FALSE; IWineD3DCubeTextureImpl *This = (IWineD3DCubeTextureImpl *)iface; + IWineD3DDeviceImpl *device = This->resource.wineD3DDevice; TRACE("(%p) : About to load texture: dirtified(%d)\n", This, This->baseTexture.dirty); 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); ENTER_GL(); diff --git a/dlls/wined3d/device.c b/dlls/wined3d/device.c index 4633a9cfcf1..7b80b4ae74c 100644 --- a/dlls/wined3d/device.c +++ b/dlls/wined3d/device.c @@ -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)); 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 * 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 @@ -377,6 +380,9 @@ static void CreateIndexBufferVBO(IWineD3DDeviceImpl *This, IWineD3DIndexBufferIm IWineD3DDeviceImpl_MarkStateDirty(This, STATE_INDEXBUFFER); 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()); GL_EXTCALL(glGenBuffersARB(1, &object->vbo)); @@ -1756,6 +1762,13 @@ static HRESULT WINAPI IWineD3DDeviceImpl_Uninit3D(IWineD3DDevice *iface, D3DCB_D 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 */ if(This->pbufferContext) DestroyContext(This, This->pbufferContext); @@ -3674,6 +3687,16 @@ static HRESULT WINAPI IWineD3DDeviceImpl_ProcessVertices(IWineD3DDevice *iface, WARN("NULL source vertex buffer\n"); 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 * a source for ProcessVertices. Avoid wasting resources by converting the * buffer and loading the VBO @@ -4103,6 +4126,9 @@ static HRESULT WINAPI IWineD3DDeviceImpl_EndScene(IWineD3DDevice *iface) { } 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 */ glFlush(); checkGLcall("glFlush"); @@ -4152,6 +4178,10 @@ static HRESULT WINAPI IWineD3DDeviceImpl_Clear(IWineD3DDevice *iface, DWORD Coun } 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); checkGLcall("glEnable GL_SCISSOR_TEST"); @@ -4755,6 +4785,9 @@ static HRESULT WINAPI IWineD3DDeviceImpl_UpdateSurface(IWineD3DDevice *iface, } ENTER_GL(); + + ActivateContext(This, This->lastActiveRenderTarget, CTXUSAGE_RESOURCELOAD); + if (GL_SUPPORT(ARB_MULTITEXTURE)) { GL_EXTCALL(glActiveTextureARB(GL_TEXTURE0_ARB)); checkGLcall("glActiveTextureARB"); @@ -4995,6 +5028,10 @@ static HRESULT WINAPI IWineD3DDeviceImpl_SetFrontBackBuffers(IWineD3DDevice *ifa if(Swapchain->backBuffer[0] != 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(); if(!Swapchain->backBuffer[0]) { /* GL was told to draw to the front buffer at creation, @@ -5248,6 +5285,7 @@ static HRESULT WINAPI IWineD3DDeviceImpl_SetCursorProperties(IWineD3DDevice* i /* some basic validation checks */ if(This->cursorTexture) { ENTER_GL(); + ActivateContext(This, This->lastActiveRenderTarget, CTXUSAGE_RESOURCELOAD); glDeleteTextures(1, &This->cursorTexture); LEAVE_GL(); This->cursorTexture = 0; @@ -5419,6 +5457,7 @@ static void updateSurfaceDesc(IWineD3DSurfaceImpl *surface, WINED3DPRESENT_PARAM } if(surface->glDescription.textureName) { ENTER_GL(); + ActivateContext(This, This->lastActiveRenderTarget, CTXUSAGE_RESOURCELOAD); glDeleteTextures(1, &surface->glDescription.textureName); LEAVE_GL(); surface->glDescription.textureName = 0; diff --git a/dlls/wined3d/indexbuffer.c b/dlls/wined3d/indexbuffer.c index ae2294aaad7..f64d6aa1905 100644 --- a/dlls/wined3d/indexbuffer.c +++ b/dlls/wined3d/indexbuffer.c @@ -59,7 +59,10 @@ static ULONG WINAPI IWineD3DIndexBufferImpl_Release(IWineD3DIndexBuffer *iface) TRACE("(%p) : Releasing from %d\n", This, ref + 1); if (ref == 0) { if(This->vbo) { + IWineD3DDeviceImpl *device = This->resource.wineD3DDevice; + ENTER_GL(); + ActivateContext(device, device->lastActiveRenderTarget, CTXUSAGE_RESOURCELOAD); /* 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 * 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) /* For now load in unlock */ if(locks == 0 && This->vbo) { + IWineD3DDeviceImpl *device = This->resource.wineD3DDevice; ENTER_GL(); + + if(device->createParms.BehaviorFlags & WINED3DCREATE_MULTITHREADED) { + ActivateContext(device, device->lastActiveRenderTarget, CTXUSAGE_RESOURCELOAD); + } + GL_EXTCALL(glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, This->vbo)); checkGLcall("glBindBufferARB"); GL_EXTCALL(glBufferSubDataARB(GL_ELEMENT_ARRAY_BUFFER_ARB, @@ -163,7 +172,7 @@ static HRESULT WINAPI IWineD3DIndexBufferImpl_Unlock(IWineD3DIndexBuffer *iface) This->dirtystart = 0; This->dirtyend = 0; /* 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; } diff --git a/dlls/wined3d/surface.c b/dlls/wined3d/surface.c index 1f4ddb616c4..c1b146535a4 100644 --- a/dlls/wined3d/surface.c +++ b/dlls/wined3d/surface.c @@ -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, This->glDescription.glFormat, This->glDescription.glType, This->resource.allocatedMemory); - ENTER_GL(); - GL_EXTCALL(glGetCompressedTexImageARB(This->glDescription.target, This->glDescription.level, This->resource.allocatedMemory)); checkGLcall("glGetCompressedTexImageARB()"); - - LEAVE_GL(); } } else { void *mem; @@ -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, This->glDescription.glFormat, This->glDescription.glType, mem); - ENTER_GL(); - glGetTexImage(This->glDescription.target, This->glDescription.level, This->glDescription.glFormat, This->glDescription.glType, mem); checkGLcall("glGetTexImage()"); - LEAVE_GL(); - if (This->Flags & SFLAG_NONPOW2) { LPBYTE src_data, dst_data; int y; @@ -258,6 +250,7 @@ ULONG WINAPI IWineD3DSurfaceImpl_Release(IWineD3DSurface *iface) { * and the lastActiveRenderTarget member shouldn't matter */ if(swapchain) { + ENTER_GL(); /* For ActivateContext */ if(swapchain->backBuffer && swapchain->backBuffer[0] != iface) { TRACE("Activating primary back buffer\n"); ActivateContext(device, swapchain->backBuffer[0], CTXUSAGE_RESOURCELOAD); @@ -272,6 +265,7 @@ ULONG WINAPI IWineD3DSurfaceImpl_Release(IWineD3DSurface *iface) { */ device->lastActiveRenderTarget = (IWineD3DSurface *) 0xdeadbabe; } + LEAVE_GL(); } else { /* May happen during ddraw uninitialization */ TRACE("Render target set, but swapchain does not exist!\n"); @@ -281,6 +275,15 @@ ULONG WINAPI IWineD3DSurfaceImpl_Release(IWineD3DSurface *iface) { if (This->glDescription.textureName != 0) { /* release the openGL texture.. */ 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); glDeleteTextures(1, &This->glDescription.textureName); LEAVE_GL(); @@ -338,13 +341,11 @@ DWORD WINAPI IWineD3DSurfaceImpl_GetPriority(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 */ IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *)iface; IWineD3DBaseTexture *baseTexture = NULL; + IWineD3DDeviceImpl *device = This->resource.wineD3DDevice; + TRACE("(%p)Checking to see if the container is a base texture\n", This); if (IWineD3DSurface_GetContainer(iface, &IID_IWineD3DBaseTexture, (void **)&baseTexture) == WINED3D_OK) { TRACE("Passing to conatiner\n"); @@ -352,10 +353,12 @@ void WINAPI IWineD3DSurfaceImpl_PreLoad(IWineD3DSurface *iface) { IWineD3DBaseTexture_Release(baseTexture); } else { TRACE("(%p) : About to load surface\n", This); + ENTER_GL(); -#if 0 /* TODO: context manager support */ - IWineD3DContextManager_PushState(This->contextManager, GL_TEXTURE_2D, ENABLED, NOW /* make sure the state is applied now */); -#endif + if(!device->isInDraw) { + ActivateContext(device, device->lastActiveRenderTarget, CTXUSAGE_RESOURCELOAD); + } + glEnable(This->glDescription.target);/* make sure texture support is enabled in this context */ if (!This->glDescription.level) { if (!This->glDescription.textureName) { @@ -377,11 +380,6 @@ void WINAPI IWineD3DSurfaceImpl_PreLoad(IWineD3DSurface *iface) { tmp = 0.9f; 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(); } return; @@ -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 */ 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) { /* 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 */ if (GL_SUPPORT(ARB_MULTITEXTURE)) { - ENTER_GL(); GL_EXTCALL(glActiveTextureARB(GL_TEXTURE0_ARB)); checkGLcall("glActiveTextureARB"); - LEAVE_GL(); } IWineD3DDeviceImpl_MarkStateDirty(This->resource.wineD3DDevice, STATE_SAMPLER(0)); IWineD3DSurface_PreLoad(iface); surface_download_data(This); + LEAVE_GL(); } /* The local copy is now up to date to the opengl one because a full download was done */ diff --git a/dlls/wined3d/swapchain.c b/dlls/wined3d/swapchain.c index 3f827ff1907..8b6187513e7 100644 --- a/dlls/wined3d/swapchain.c +++ b/dlls/wined3d/swapchain.c @@ -146,6 +146,8 @@ static HRESULT WINAPI IWineD3DSwapChainImpl_Present(IWineD3DSwapChain *iface, CO 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 :-) */ if(This->wineD3DDevice->bCursorVisible && This->wineD3DDevice->cursorTexture) { IWineD3DSurfaceImpl cursor; diff --git a/dlls/wined3d/texture.c b/dlls/wined3d/texture.c index e9a78cc5d08..cc8a83a9ffd 100644 --- a/dlls/wined3d/texture.c +++ b/dlls/wined3d/texture.c @@ -97,11 +97,21 @@ static void WINAPI IWineD3DTextureImpl_PreLoad(IWineD3DTexture *iface) { unsigned int i; BOOL setGlTextureDesc = FALSE; IWineD3DTextureImpl *This = (IWineD3DTextureImpl *)iface; + IWineD3DDeviceImpl *device = This->resource.wineD3DDevice; TRACE("(%p) : About to load texture\n", This); 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); ENTER_GL(); /* If were dirty then reload the surfaces */ diff --git a/dlls/wined3d/utils.c b/dlls/wined3d/utils.c index 56d19ee41e5..dadcc54dfaf 100644 --- a/dlls/wined3d/utils.c +++ b/dlls/wined3d/utils.c @@ -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], &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) { @@ -1082,7 +1083,6 @@ void set_tex_op_nvrc(IWineD3DDevice *iface, BOOL is_alpha, int stage, WINED3DTEX checkGLcall("set_tex_op_nvrc()\n"); - LEAVE_GL(); } 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 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 the form (a1 a2). However, some of the more complex operations @@ -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); checkGLcall("GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE4_NV"); - LEAVE_GL(); return; } } /* GL_NV_texture_env_combine4 */ @@ -2148,7 +2147,6 @@ void set_tex_op(IWineD3DDevice *iface, BOOL isAlpha, int Stage, WINED3DTEXTUREOP break; default: 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; } } @@ -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)); checkGLcall("GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, useext(GL_COMBINE)"); - LEAVE_GL(); return; } } - LEAVE_GL(); - /* After all the extensions, if still unhandled, report fixme */ FIXME("Unhandled texture operation %s\n", debug_d3dtop(op)); #undef GLINFO_LOCATION diff --git a/dlls/wined3d/vertexbuffer.c b/dlls/wined3d/vertexbuffer.c index e832439ec60..6fd48a9a036 100644 --- a/dlls/wined3d/vertexbuffer.c +++ b/dlls/wined3d/vertexbuffer.c @@ -62,7 +62,10 @@ static ULONG WINAPI IWineD3DVertexBufferImpl_Release(IWineD3DVertexBuffer *iface if (ref == 0) { if(This->vbo) { + IWineD3DDeviceImpl *device = This->resource.wineD3DDevice; + ENTER_GL(); + ActivateContext(device, device->lastActiveRenderTarget, CTXUSAGE_RESOURCELOAD); GL_EXTCALL(glDeleteBuffersARB(1, &This->vbo)); checkGLcall("glDeleteBuffersARB"); LEAVE_GL(); @@ -244,6 +247,7 @@ inline BOOL WINAPI IWineD3DVertexBufferImpl_FindDecl(IWineD3DVertexBufferImpl *T static void WINAPI IWineD3DVertexBufferImpl_PreLoad(IWineD3DVertexBuffer *iface) { IWineD3DVertexBufferImpl *This = (IWineD3DVertexBufferImpl *) iface; + IWineD3DDeviceImpl *device = This->resource.wineD3DDevice; BYTE *data; UINT start = 0, end = 0, stride = 0; BOOL declChanged = FALSE; @@ -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 */ - if(This->resource.wineD3DDevice->isInDraw && This->bindCount > 0) { + if(device->isInDraw && This->bindCount > 0) { declChanged = IWineD3DVertexBufferImpl_FindDecl(This); } else if(This->Flags & VBFLAG_HASDESC) { /* 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 if(This->declChanges > VB_MAXDECLCHANGES) { FIXME("Too much declaration changes, stopping converting\n"); ENTER_GL(); + ActivateContext(device, device->lastActiveRenderTarget, CTXUSAGE_RESOURCELOAD); GL_EXTCALL(glDeleteBuffersARB(1, &This->vbo)); checkGLcall("glDeleteBuffersARB"); LEAVE_GL(); @@ -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 * rarely */ - IWineD3DDeviceImpl_MarkStateDirty(This->resource.wineD3DDevice, STATE_STREAMSRC); + IWineD3DDeviceImpl_MarkStateDirty(device, STATE_STREAMSRC); return; } @@ -337,6 +342,9 @@ static void WINAPI IWineD3DVertexBufferImpl_PreLoad(IWineD3DVertexBuffer *if TRACE("No conversion needed, locking directly into the VBO in future\n"); ENTER_GL(); + if(!device->isInDraw) { + ActivateContext(device, device->lastActiveRenderTarget, CTXUSAGE_RESOURCELOAD); + } GL_EXTCALL(glBindBufferARB(GL_ARRAY_BUFFER_ARB, This->vbo)); checkGLcall("glBindBufferARB"); 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 This->strided.u.s.specular.dwType == WINED3DDECLTYPE_SHORT4 || This->strided.u.s.specular.dwType == WINED3DDECLTYPE_D3DCOLOR); ENTER_GL(); + if(!device->isInDraw) { + ActivateContext(device, device->lastActiveRenderTarget, CTXUSAGE_RESOURCELOAD); + } GL_EXTCALL(glBindBufferARB(GL_ARRAY_BUFFER_ARB, This->vbo)); checkGLcall("glBindBufferARB"); GL_EXTCALL(glBufferSubDataARB(GL_ARRAY_BUFFER_ARB, start, end - start, data)); diff --git a/dlls/wined3d/volumetexture.c b/dlls/wined3d/volumetexture.c index 46e0c4d7cbc..1d75bdc109f 100644 --- a/dlls/wined3d/volumetexture.c +++ b/dlls/wined3d/volumetexture.c @@ -94,12 +94,16 @@ static void WINAPI IWineD3DVolumeTextureImpl_PreLoad(IWineD3DVolumeTexture *ifac /* Overrider the IWineD3DResource Preload method */ UINT i; IWineD3DVolumeTextureImpl *This = (IWineD3DVolumeTextureImpl *)iface; + IWineD3DDeviceImpl *device = This->resource.wineD3DDevice; TRACE("(%p) : About to load texture\n", This); IWineD3DVolumeTexture_BindTexture(iface); ENTER_GL(); + if(!device->isInDraw) { + ActivateContext(device, device->lastActiveRenderTarget, CTXUSAGE_RESOURCELOAD); + } /* If were dirty then reload the volumes */ if(This->baseTexture.dirty) { for (i = 0; i < This->baseTexture.levels; i++) {