📄 surface.c
字号:
GLint fmt, type;
BYTE *mem;
UINT bpp;
UINT pitch = IWineD3DSurface_GetPitch((IWineD3DSurface *) This); /* target is argb, 4 byte */
glDisable(GL_TEXTURE_2D);
vcheckGLcall("glDisable(GL_TEXTURE_2D)");
glFlush();
vcheckGLcall("glFlush");
glGetIntegerv(GL_PACK_SWAP_BYTES, &prev_store);
vcheckGLcall("glIntegerv");
glGetIntegerv(GL_CURRENT_RASTER_POSITION, &prev_rasterpos[0]);
vcheckGLcall("glIntegerv");
glPixelZoom(1.0, -1.0);
vcheckGLcall("glPixelZoom");
/* If not fullscreen, we need to skip a number of bytes to find the next row of data */
glGetIntegerv(GL_UNPACK_ROW_LENGTH, &skipBytes);
glPixelStorei(GL_UNPACK_ROW_LENGTH, This->currentDesc.Width);
glRasterPos3i(This->lockedRect.left, This->lockedRect.top, 1);
vcheckGLcall("glRasterPos2f");
/* Some drivers(radeon dri, others?) don't like exceptions during
* glDrawPixels. If the surface is a DIB section, it might be in GDIMode
* after ReleaseDC. Reading it will cause an exception, which x11drv will
* catch to put the dib section in InSync mode, which leads to a crash
* and a blocked x server on my radeon card.
*
* The following lines read the dib section so it is put in inSync mode
* before glDrawPixels is called and the crash is prevented. There won't
* be any interfering gdi accesses, because UnlockRect is called from
* ReleaseDC, and the app won't use the dc any more afterwards.
*/
if(This->Flags & SFLAG_DIBSECTION) {
volatile BYTE read;
read = This->resource.allocatedMemory[0];
}
switch (This->resource.format) {
/* No special care needed */
case WINED3DFMT_A4R4G4B4:
case WINED3DFMT_R5G6B5:
case WINED3DFMT_A1R5G5B5:
case WINED3DFMT_R8G8B8:
type = This->glDescription.glType;
fmt = This->glDescription.glFormat;
mem = This->resource.allocatedMemory;
bpp = This->bytesPerPixel;
break;
case WINED3DFMT_X4R4G4B4:
{
int size;
unsigned short *data;
data = (unsigned short *)This->resource.allocatedMemory;
size = (This->lockedRect.bottom - This->lockedRect.top) * (This->lockedRect.right - This->lockedRect.left);
while(size > 0) {
*data |= 0xF000;
data++;
size--;
}
type = This->glDescription.glType;
fmt = This->glDescription.glFormat;
mem = This->resource.allocatedMemory;
bpp = This->bytesPerPixel;
}
break;
case WINED3DFMT_X1R5G5B5:
{
int size;
unsigned short *data;
data = (unsigned short *)This->resource.allocatedMemory;
size = (This->lockedRect.bottom - This->lockedRect.top) * (This->lockedRect.right - This->lockedRect.left);
while(size > 0) {
*data |= 0x8000;
data++;
size--;
}
type = This->glDescription.glType;
fmt = This->glDescription.glFormat;
mem = This->resource.allocatedMemory;
bpp = This->bytesPerPixel;
}
break;
case WINED3DFMT_X8R8G8B8:
{
/* make sure the X byte is set to alpha on, since it
could be any random value. This fixes the intro movie in Pirates! */
int size;
unsigned int *data;
data = (unsigned int *)This->resource.allocatedMemory;
size = (This->lockedRect.bottom - This->lockedRect.top) * (This->lockedRect.right - This->lockedRect.left);
while(size > 0) {
*data |= 0xFF000000;
data++;
size--;
}
}
/* Fall through */
case WINED3DFMT_A8R8G8B8:
{
glPixelStorei(GL_PACK_SWAP_BYTES, TRUE);
vcheckGLcall("glPixelStorei");
storechanged = TRUE;
type = This->glDescription.glType;
fmt = This->glDescription.glFormat;
mem = This->resource.allocatedMemory;
bpp = This->bytesPerPixel;
}
break;
case WINED3DFMT_A2R10G10B10:
{
glPixelStorei(GL_PACK_SWAP_BYTES, TRUE);
vcheckGLcall("glPixelStorei");
storechanged = TRUE;
type = This->glDescription.glType;
fmt = This->glDescription.glFormat;
mem = This->resource.allocatedMemory;
bpp = This->bytesPerPixel;
}
break;
case WINED3DFMT_P8:
{
int height = This->glRect.bottom - This->glRect.top;
type = GL_UNSIGNED_BYTE;
fmt = GL_RGBA;
mem = HeapAlloc(GetProcessHeap(), 0, This->resource.size * sizeof(DWORD));
if(!mem) {
ERR("Out of memory\n");
return;
}
memory_allocated = TRUE;
d3dfmt_convert_surface(This->resource.allocatedMemory,
mem,
pitch,
pitch,
height,
pitch * 4,
CONVERT_PALETTED,
This);
bpp = This->bytesPerPixel * 4;
pitch *= 4;
}
break;
default:
FIXME("Unsupported Format %u in locking func\n", This->resource.format);
/* Give it a try */
type = This->glDescription.glType;
fmt = This->glDescription.glFormat;
mem = This->resource.allocatedMemory;
bpp = This->bytesPerPixel;
}
glDrawPixels(This->lockedRect.right - This->lockedRect.left,
(This->lockedRect.bottom - This->lockedRect.top)-1,
fmt, type,
mem + bpp * This->lockedRect.left + pitch * This->lockedRect.top);
checkGLcall("glDrawPixels");
glPixelZoom(1.0,1.0);
vcheckGLcall("glPixelZoom");
glRasterPos3iv(&prev_rasterpos[0]);
vcheckGLcall("glRasterPos3iv");
/* Reset to previous pack row length */
glPixelStorei(GL_UNPACK_ROW_LENGTH, skipBytes);
vcheckGLcall("glPixelStorei GL_UNPACK_ROW_LENGTH");
if(storechanged) {
glPixelStorei(GL_PACK_SWAP_BYTES, prev_store);
vcheckGLcall("glPixelStorei GL_PACK_SWAP_BYTES");
}
/* Blitting environment requires that 2D texturing is enabled. It was turned off before,
* turn it on again
*/
glEnable(GL_TEXTURE_2D);
checkGLcall("glEnable(GL_TEXTURE_2D)");
if(memory_allocated) HeapFree(GetProcessHeap(), 0, mem);
return;
}
static void flush_to_framebuffer_texture(IWineD3DSurfaceImpl *This) {
float glTexCoord[4];
glTexCoord[0] = (float) This->lockedRect.left / (float) This->pow2Width; /* left */
glTexCoord[1] = (float) This->lockedRect.right / (float) This->pow2Width; /* right */
glTexCoord[2] = (float) This->lockedRect.top / (float) This->pow2Height; /* top */
glTexCoord[3] = (float) This->lockedRect.bottom / (float) This->pow2Height; /* bottom */
IWineD3DSurface_PreLoad((IWineD3DSurface *) This);
ENTER_GL();
glBindTexture(GL_TEXTURE_2D, This->glDescription.textureName);
checkGLcall("glEnable glBindTexture");
/* No filtering for blts */
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
checkGLcall("glTexParameteri");
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
checkGLcall("glTexParameteri");
/* Start drawing a quad */
glBegin(GL_QUADS);
glColor3d(1.0f, 1.0f, 1.0f);
glTexCoord2f(glTexCoord[0], glTexCoord[2]);
glVertex3f(This->lockedRect.left, This->lockedRect.top, 0.0);
glTexCoord2f(glTexCoord[0], glTexCoord[3]);
glVertex3f(This->lockedRect.left, This->lockedRect.bottom, 0.0);
glTexCoord2f(glTexCoord[1], glTexCoord[3]);
glVertex3d(This->lockedRect.right, This->lockedRect.bottom, 0.0);
glTexCoord2f(glTexCoord[1], glTexCoord[2]);
glVertex3f(This->lockedRect.right, This->lockedRect.top, 0.0);
glEnd();
checkGLcall("glEnd");
/* Unbind the texture */
glBindTexture(GL_TEXTURE_2D, 0);
checkGLcall("glEnable glBindTexture");
LEAVE_GL();
}
static HRESULT WINAPI IWineD3DSurfaceImpl_UnlockRect(IWineD3DSurface *iface) {
IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *)iface;
IWineD3DDeviceImpl *myDevice = This->resource.wineD3DDevice;
IWineD3DSwapChainImpl *swapchain = NULL;
if (!(This->Flags & SFLAG_LOCKED)) {
WARN("trying to Unlock an unlocked surf@%p\n", This);
return WINED3DERR_INVALIDCALL;
}
TRACE("(%p) : dirtyfied(%d)\n", This, This->Flags & (SFLAG_INDRAWABLE | SFLAG_INTEXTURE) ? 0 : 1);
if (This->Flags & (SFLAG_INDRAWABLE | SFLAG_INTEXTURE)) {
TRACE("(%p) : Not Dirtified so nothing to do, return now\n", This);
goto unlock_end;
}
IWineD3DSurface_GetContainer(iface, &IID_IWineD3DSwapChain, (void **)&swapchain);
if(swapchain || iface == myDevice->render_targets[0]) {
if(wined3d_settings.rendertargetlock_mode == RTL_DISABLE) {
static BOOL warned = FALSE;
if(!warned) {
ERR("The application tries to write to the render target, but render target locking is disabled\n");
warned = TRUE;
}
if(swapchain) IWineD3DSwapChain_Release((IWineD3DSwapChain *) swapchain);
goto unlock_end;
}
/* Activate the correct context for the render target */
ActivateContext(myDevice, iface, CTXUSAGE_BLIT);
ENTER_GL();
if(!swapchain) {
/* Primary offscreen render target */
TRACE("Offscreen render target\n");
glDrawBuffer(myDevice->offscreenBuffer);
checkGLcall("glDrawBuffer(myDevice->offscreenBuffer)");
} else {
GLenum buffer = surface_get_gl_buffer(iface, (IWineD3DSwapChain *)swapchain);
TRACE("Unlocking %#x buffer\n", buffer);
glDrawBuffer(buffer);
checkGLcall("glDrawBuffer");
IWineD3DSwapChain_Release((IWineD3DSwapChain *)swapchain);
}
switch(wined3d_settings.rendertargetlock_mode) {
case RTL_AUTO:
case RTL_READDRAW:
case RTL_TEXDRAW:
flush_to_framebuffer_drawpixels(This);
break;
case RTL_READTEX:
case RTL_TEXTEX:
flush_to_framebuffer_texture(This);
break;
}
if(!swapchain) {
glDrawBuffer(myDevice->offscreenBuffer);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -