📄 surface.c
字号:
checkGLcall("glDrawBuffer(myDevice->offscreenBuffer)");
} else if(swapchain->backBuffer) {
glDrawBuffer(GL_BACK);
checkGLcall("glDrawBuffer(GL_BACK)");
} else {
glDrawBuffer(GL_FRONT);
checkGLcall("glDrawBuffer(GL_FRONT)");
}
LEAVE_GL();
This->dirtyRect.left = This->currentDesc.Width;
This->dirtyRect.top = This->currentDesc.Height;
This->dirtyRect.right = 0;
This->dirtyRect.bottom = 0;
This->Flags |= SFLAG_INDRAWABLE;
} else if(iface == myDevice->stencilBufferTarget) {
FIXME("Depth Stencil buffer locking is not implemented\n");
} else {
/* The rest should be a normal texture */
IWineD3DBaseTextureImpl *impl;
/* Check if the texture is bound, if yes dirtify the sampler to force a re-upload of the texture
* Can't load the texture here because PreLoad may destroy and recreate the gl texture, so sampler
* states need resetting
*/
if(IWineD3DSurface_GetContainer(iface, &IID_IWineD3DBaseTexture, (void **)&impl) == WINED3D_OK) {
if(impl->baseTexture.bindCount) {
IWineD3DDeviceImpl_MarkStateDirty(myDevice, STATE_SAMPLER(impl->baseTexture.sampler));
}
IWineD3DBaseTexture_Release((IWineD3DBaseTexture *) impl);
}
}
unlock_end:
This->Flags &= ~SFLAG_LOCKED;
memset(&This->lockedRect, 0, sizeof(RECT));
return WINED3D_OK;
}
HRESULT WINAPI IWineD3DSurfaceImpl_GetDC(IWineD3DSurface *iface, HDC *pHDC) {
IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *)iface;
WINED3DLOCKED_RECT lock;
UINT usage;
BITMAPINFO* b_info;
HDC ddc;
DWORD *masks;
HRESULT hr;
RGBQUAD col[256];
const StaticPixelFormatDesc *formatEntry = getFormatDescEntry(This->resource.format, NULL, NULL);
TRACE("(%p)->(%p)\n",This,pHDC);
if(This->Flags & SFLAG_USERPTR) {
ERR("Not supported on surfaces with an application-provided surfaces\n");
return WINEDDERR_NODC;
}
/* Give more detailed info for ddraw */
if (This->Flags & SFLAG_DCINUSE)
return WINEDDERR_DCALREADYCREATED;
/* Can't GetDC if the surface is locked */
if (This->Flags & SFLAG_LOCKED)
return WINED3DERR_INVALIDCALL;
memset(&lock, 0, sizeof(lock)); /* To be sure */
/* Create a DIB section if there isn't a hdc yet */
if(!This->hDC) {
int extraline = 0;
SYSTEM_INFO sysInfo;
void *oldmem = This->resource.allocatedMemory;
switch (This->bytesPerPixel) {
case 2:
case 4:
/* Allocate extra space to store the RGB bit masks. */
b_info = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(BITMAPINFOHEADER) + 3 * sizeof(DWORD));
break;
case 3:
b_info = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(BITMAPINFOHEADER));
break;
default:
/* Allocate extra space for a palette. */
b_info = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
sizeof(BITMAPINFOHEADER)
+ sizeof(RGBQUAD)
* (1 << (This->bytesPerPixel * 8)));
break;
}
if (!b_info)
return E_OUTOFMEMORY;
/* Some apps access the surface in via DWORDs, and do not take the necessary care at the end of the
* surface. So we need at least extra 4 bytes at the end of the surface. Check against the page size,
* if the last page used for the surface has at least 4 spare bytes we're safe, otherwise
* add an extra line to the dib section
*/
GetSystemInfo(&sysInfo);
if( ((This->resource.size + 3) % sysInfo.dwPageSize) < 4) {
extraline = 1;
TRACE("Adding an extra line to the dib section\n");
}
b_info->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
/* TODO: Is there a nicer way to force a specific alignment? (8 byte for ddraw) */
b_info->bmiHeader.biWidth = IWineD3DSurface_GetPitch(iface) / This->bytesPerPixel;
b_info->bmiHeader.biHeight = -This->currentDesc.Height -extraline;
b_info->bmiHeader.biSizeImage = ( This->currentDesc.Height + extraline) * IWineD3DSurface_GetPitch(iface);
b_info->bmiHeader.biPlanes = 1;
b_info->bmiHeader.biBitCount = This->bytesPerPixel * 8;
b_info->bmiHeader.biXPelsPerMeter = 0;
b_info->bmiHeader.biYPelsPerMeter = 0;
b_info->bmiHeader.biClrUsed = 0;
b_info->bmiHeader.biClrImportant = 0;
/* Get the bit masks */
masks = (DWORD *) &(b_info->bmiColors);
switch (This->resource.format) {
case WINED3DFMT_R8G8B8:
usage = DIB_RGB_COLORS;
b_info->bmiHeader.biCompression = BI_RGB;
break;
case WINED3DFMT_X1R5G5B5:
case WINED3DFMT_A1R5G5B5:
case WINED3DFMT_A4R4G4B4:
case WINED3DFMT_X4R4G4B4:
case WINED3DFMT_R3G3B2:
case WINED3DFMT_A8R3G3B2:
case WINED3DFMT_A2B10G10R10:
case WINED3DFMT_A8B8G8R8:
case WINED3DFMT_X8B8G8R8:
case WINED3DFMT_A2R10G10B10:
case WINED3DFMT_R5G6B5:
case WINED3DFMT_A16B16G16R16:
usage = 0;
b_info->bmiHeader.biCompression = BI_BITFIELDS;
masks[0] = formatEntry->redMask;
masks[1] = formatEntry->greenMask;
masks[2] = formatEntry->blueMask;
break;
default:
/* Don't know palette */
b_info->bmiHeader.biCompression = BI_RGB;
usage = 0;
break;
}
ddc = GetDC(0);
if (ddc == 0) {
HeapFree(GetProcessHeap(), 0, b_info);
return HRESULT_FROM_WIN32(GetLastError());
}
TRACE("Creating a DIB section with size %dx%dx%d, size=%d\n", b_info->bmiHeader.biWidth, b_info->bmiHeader.biHeight, b_info->bmiHeader.biBitCount, b_info->bmiHeader.biSizeImage);
This->dib.DIBsection = CreateDIBSection(ddc, b_info, usage, &This->dib.bitmap_data, 0 /* Handle */, 0 /* Offset */);
ReleaseDC(0, ddc);
if (!This->dib.DIBsection) {
ERR("CreateDIBSection failed!\n");
HeapFree(GetProcessHeap(), 0, b_info);
return HRESULT_FROM_WIN32(GetLastError());
}
TRACE("DIBSection at : %p\n", This->dib.bitmap_data);
/* copy the existing surface to the dib section */
if(This->resource.allocatedMemory) {
memcpy(This->dib.bitmap_data, This->resource.allocatedMemory, b_info->bmiHeader.biSizeImage);
/* We won't need that any more */
} else {
/* This is to make LockRect read the gl Texture although memory is allocated */
This->Flags &= ~SFLAG_INSYSMEM;
}
HeapFree(GetProcessHeap(), 0, b_info);
/* Use the dib section from now on */
This->resource.allocatedMemory = This->dib.bitmap_data;
/* Now allocate a HDC */
This->hDC = CreateCompatibleDC(0);
This->dib.holdbitmap = SelectObject(This->hDC, This->dib.DIBsection);
TRACE("using wined3d palette %p\n", This->palette);
SelectPalette(This->hDC,
This->palette ? This->palette->hpal : 0,
FALSE);
This->Flags |= SFLAG_DIBSECTION;
if(This->Flags & SFLAG_CLIENT) {
IWineD3DSurface_PreLoad(iface);
}
HeapFree(GetProcessHeap(), 0, oldmem);
}
/* Lock the surface */
hr = IWineD3DSurface_LockRect(iface,
&lock,
NULL,
0);
if(FAILED(hr)) {
ERR("IWineD3DSurface_LockRect failed with hr = %08x\n", hr);
/* keep the dib section */
return hr;
}
if(This->resource.format == WINED3DFMT_P8 ||
This->resource.format == WINED3DFMT_A8P8) {
unsigned int n;
if(This->palette) {
PALETTEENTRY ent[256];
GetPaletteEntries(This->palette->hpal, 0, 256, ent);
for (n=0; n<256; n++) {
col[n].rgbRed = ent[n].peRed;
col[n].rgbGreen = ent[n].peGreen;
col[n].rgbBlue = ent[n].peBlue;
col[n].rgbReserved = 0;
}
} else {
IWineD3DDeviceImpl *device = This->resource.wineD3DDevice;
for (n=0; n<256; n++) {
col[n].rgbRed = device->palettes[device->currentPalette][n].peRed;
col[n].rgbGreen = device->palettes[device->currentPalette][n].peGreen;
col[n].rgbBlue = device->palettes[device->currentPalette][n].peBlue;
col[n].rgbReserved = 0;
}
}
SetDIBColorTable(This->hDC, 0, 256, col);
}
*pHDC = This->hDC;
TRACE("returning %p\n",*pHDC);
This->Flags |= SFLAG_DCINUSE;
return WINED3D_OK;
}
HRESULT WINAPI IWineD3DSurfaceImpl_ReleaseDC(IWineD3DSurface *iface, HDC hDC) {
IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *)iface;
TRACE("(%p)->(%p)\n",This,hDC);
if (!(This->Flags & SFLAG_DCINUSE))
return WINED3DERR_INVALIDCALL;
/* we locked first, so unlock now */
IWineD3DSurface_UnlockRect(iface);
This->Flags &= ~SFLAG_DCINUSE;
return WINED3D_OK;
}
/* ******************************************************
IWineD3DSurface Internal (No mapping to directx api) parts follow
****************************************************** */
HRESULT d3dfmt_get_conv(IWineD3DSurfaceImpl *This, BOOL need_alpha_ck, BOOL use_texturing, GLenum *format, GLenum *internal, GLenum *type, CONVERT_TYPES *convert, int *target_bpp, BOOL srgb_mode) {
BOOL colorkey_active = need_alpha_ck && (This->CKeyFlags & WINEDDSD_CKSRCBLT);
const GlPixelFormatDesc *glDesc;
getFormatDescEntry(This->resource.format, &GLINFO_LOCATION, &glDesc);
/* Default values: From the surface */
*format = glDesc->glFormat;
*internal = srgb_mode?glDesc->glGammaInternal:glDesc->glInternal;
*type = glDesc->glType;
*convert = NO_CONVERSION;
*target_bpp = This->bytesPerPixel;
/* Ok, now look if we have to do any conversion */
switch(This->resource.format) {
case WINED3DFMT_P8:
/* ****************
Paletted Texture
**************** */
/* Use conversion when the paletted texture extension is not available, or when it is available make sure it is used
* for texturing as it won't work for calls like glDraw-/glReadPixels and further also use conversion in case of color keying.
*/
if(!GL_SUPPORT(EXT_PALETTED_TEXTURE) || colorkey_active || (!use_texturing && GL_SUPPORT(EXT_PALETTED_TEXTURE)) ) {
*format = GL_RGBA;
*internal = GL_RGBA;
*type = GL_UNSIGNED_BYTE;
*target_bpp = 4;
if(colorkey_active) {
*convert = CONVERT_PALETTED_CK;
} else {
*convert =
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -