📄 dib.c
字号:
/* DIBSection DirectDrawSurface driver * * Copyright 1997-2000 Marcus Meissner * Copyright 1998-2000 Lionel Ulmer * Copyright 2000-2001 TransGaming Technologies Inc. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */#include "config.h"#include <assert.h>#include <stdlib.h>#include <string.h>#define NONAMELESSUNION#define NONAMELESSSTRUCT#include "winerror.h"#include "bitmap.h"#include "wine/debug.h"#include "ddraw_private.h"#include "dsurface/main.h"#include "dsurface/dib.h"WINE_DEFAULT_DEBUG_CHANNEL(ddraw);static ICOM_VTABLE(IDirectDrawSurface7) DIB_IDirectDrawSurface7_VTable;/* Return the width of a DIB bitmap in bytes. DIB bitmap data is 32-bit aligned. */inline static int get_dib_width_bytes( int width, int depth ){ int words; switch(depth) { case 1: words = (width + 31) / 32; break; case 4: words = (width + 7) / 8; break; case 8: words = (width + 3) / 4; break; case 15: case 16: words = (width + 1) / 2; break; case 24: words = (width * 3 + 3)/4; break; default: WARN("(%d): Unsupported depth\n", depth ); /* fall through */ case 32: words = width; break; } return 4 * words;}static HRESULT create_dib(IDirectDrawSurfaceImpl* This){ BITMAPINFO* b_info; UINT usage; HDC ddc; DIB_DirectDrawSurfaceImpl* priv = This->private; assert(This->surface_desc.lpSurface != NULL); switch (This->surface_desc.u4.ddpfPixelFormat.u1.dwRGBBitCount) { case 16: case 32: /* Allocate extra space to store the RGB bit masks. */ b_info = (BITMAPINFO*)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(BITMAPINFOHEADER) + 3 * sizeof(DWORD)); break; case 24: b_info = (BITMAPINFO*)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(BITMAPINFOHEADER)); break; default: /* Allocate extra space for a palette. */ b_info = (BITMAPINFO*)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(BITMAPINFOHEADER) + sizeof(RGBQUAD) * (1 << This->surface_desc.u4.ddpfPixelFormat.u1.dwRGBBitCount)); break; } b_info->bmiHeader.biSize = sizeof(BITMAPINFOHEADER); b_info->bmiHeader.biWidth = This->surface_desc.dwWidth; b_info->bmiHeader.biHeight = -This->surface_desc.dwHeight; b_info->bmiHeader.biPlanes = 1; b_info->bmiHeader.biBitCount = This->surface_desc.u4.ddpfPixelFormat.u1.dwRGBBitCount; if ((This->surface_desc.u4.ddpfPixelFormat.u1.dwRGBBitCount != 16) && (This->surface_desc.u4.ddpfPixelFormat.u1.dwRGBBitCount != 32)) b_info->bmiHeader.biCompression = BI_RGB; else b_info->bmiHeader.biCompression = BI_BITFIELDS; b_info->bmiHeader.biSizeImage = (This->surface_desc.u4.ddpfPixelFormat.u1.dwRGBBitCount / 8) * This->surface_desc.dwWidth * This->surface_desc.dwHeight; b_info->bmiHeader.biXPelsPerMeter = 0; b_info->bmiHeader.biYPelsPerMeter = 0; b_info->bmiHeader.biClrUsed = 0; b_info->bmiHeader.biClrImportant = 0; if (!This->surface_desc.u1.lPitch) { /* This can't happen, right? */ /* or use GDI_GetObj to get it from the created DIB? */ This->surface_desc.u1.lPitch = get_dib_width_bytes(b_info->bmiHeader.biWidth, b_info->bmiHeader.biBitCount); This->surface_desc.dwFlags |= DDSD_PITCH; } switch (This->surface_desc.u4.ddpfPixelFormat.u1.dwRGBBitCount) { case 16: case 32: { DWORD *masks = (DWORD *) &(b_info->bmiColors); usage = 0; masks[0] = This->surface_desc.u4.ddpfPixelFormat.u2.dwRBitMask; masks[1] = This->surface_desc.u4.ddpfPixelFormat.u3.dwGBitMask; masks[2] = This->surface_desc.u4.ddpfPixelFormat.u4.dwBBitMask; } break; case 24: /* Nothing to do */ usage = DIB_RGB_COLORS; break; default: /* Don't know palette */ usage = 0; break; } ddc = CreateDCA("DISPLAY", NULL, NULL, NULL); if (ddc == 0) { HeapFree(GetProcessHeap(), 0, b_info); return HRESULT_FROM_WIN32(GetLastError()); } priv->dib.DIBsection = DIB_CreateDIBSection(ddc, b_info, usage, &(priv->dib.bitmap_data), 0, (DWORD)This->surface_desc.lpSurface, This->surface_desc.u1.lPitch); DeleteDC(ddc); if (!priv->dib.DIBsection) { ERR("CreateDIBSection failed!\n"); HeapFree(GetProcessHeap(), 0, b_info); return HRESULT_FROM_WIN32(GetLastError()); } TRACE("DIBSection at : %p\n", priv->dib.bitmap_data); if (!This->surface_desc.lpSurface) { This->surface_desc.lpSurface = priv->dib.bitmap_data; This->surface_desc.dwFlags |= DDSD_LPSURFACE; } HeapFree(GetProcessHeap(), 0, b_info); /* I don't think it's worth checking for this. */ if (priv->dib.bitmap_data != This->surface_desc.lpSurface) ERR("unexpected error creating DirectDrawSurface DIB section\n"); /* this seems like a good place to put the handle for HAL driver use */ This->global_more.hKernelSurface = (ULONG_PTR)priv->dib.DIBsection; return S_OK;}void DIB_DirectDrawSurface_final_release(IDirectDrawSurfaceImpl* This){ DIB_DirectDrawSurfaceImpl* priv = This->private; DeleteObject(priv->dib.DIBsection); if (!priv->dib.client_memory) VirtualFree(This->surface_desc.lpSurface, 0, MEM_RELEASE); Main_DirectDrawSurface_final_release(This);}HRESULT DIB_DirectDrawSurface_duplicate_surface(IDirectDrawSurfaceImpl* This, LPDIRECTDRAWSURFACE7* ppDup){ return DIB_DirectDrawSurface_Create(This->ddraw_owner, &This->surface_desc, ppDup, NULL);}HRESULT DIB_DirectDrawSurface_Construct(IDirectDrawSurfaceImpl *This, IDirectDrawImpl *pDD, const DDSURFACEDESC2 *pDDSD){ HRESULT hr; DIB_DirectDrawSurfaceImpl* priv = This->private; TRACE("(%p)->(%p,%p)\n",This,pDD,pDDSD); hr = Main_DirectDrawSurface_Construct(This, pDD, pDDSD); if (FAILED(hr)) return hr; ICOM_INIT_INTERFACE(This, IDirectDrawSurface7, DIB_IDirectDrawSurface7_VTable); This->final_release = DIB_DirectDrawSurface_final_release; This->duplicate_surface = DIB_DirectDrawSurface_duplicate_surface; This->flip_data = DIB_DirectDrawSurface_flip_data; This->get_dc = DIB_DirectDrawSurface_get_dc; This->release_dc = DIB_DirectDrawSurface_release_dc; This->hDC = NULL; This->set_palette = DIB_DirectDrawSurface_set_palette; This->update_palette = DIB_DirectDrawSurface_update_palette; TRACE("(%ldx%ld, pitch=%ld)\n", This->surface_desc.dwWidth, This->surface_desc.dwHeight, This->surface_desc.u1.lPitch); /* XXX load dwWidth and dwHeight from pDD if they are not specified? */ if (This->surface_desc.dwFlags & DDSD_LPSURFACE) { /* "Client memory": it is managed by the application. */ /* XXX What if lPitch is not set? Use dwWidth or fail? */ priv->dib.client_memory = TRUE; } else { if (!(This->surface_desc.dwFlags & DDSD_PITCH)) { int pitch = This->surface_desc.u1.lPitch; if (pitch % 8 != 0) pitch += 8 - (pitch % 8); } /* XXX else: how should lPitch be verified? */ This->surface_desc.dwFlags |= DDSD_PITCH|DDSD_LPSURFACE; This->surface_desc.lpSurface = VirtualAlloc(NULL, This->surface_desc.u1.lPitch * This->surface_desc.dwHeight + 4, /* The + 4 here is for dumb games reading after the end of the surface when reading the last byte / half using word access */ MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE); if (This->surface_desc.lpSurface == NULL) { Main_DirectDrawSurface_final_release(This); return HRESULT_FROM_WIN32(GetLastError()); } priv->dib.client_memory = FALSE; } hr = create_dib(This); if (FAILED(hr)) { if (!priv->dib.client_memory) VirtualFree(This->surface_desc.lpSurface, 0, MEM_RELEASE); Main_DirectDrawSurface_final_release(This); return hr; } return DD_OK;}/* Not an API */HRESULT DIB_DirectDrawSurface_Create(IDirectDrawImpl *pDD, const DDSURFACEDESC2 *pDDSD, LPDIRECTDRAWSURFACE7 *ppSurf, IUnknown *pUnkOuter){ IDirectDrawSurfaceImpl* This; HRESULT hr; assert(pUnkOuter == NULL); This = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*This) + sizeof(DIB_DirectDrawSurfaceImpl)); if (This == NULL) return E_OUTOFMEMORY; This->private = (DIB_DirectDrawSurfaceImpl*)(This+1); hr = DIB_DirectDrawSurface_Construct(This, pDD, pDDSD); if (FAILED(hr)) HeapFree(GetProcessHeap(), 0, This); else *ppSurf = ICOM_INTERFACE(This, IDirectDrawSurface7); return hr;}/* AddAttachedSurface: generic *//* AddOverlayDirtyRect: generic, unimplemented */static HRESULT _Blt_ColorFill( LPBYTE buf, int width, int height, int bpp, LONG lPitch, DWORD color) { int x, y; LPBYTE first; /* Do first row */#define COLORFILL_ROW(type) { \ type *d = (type *) buf; \ for (x = 0; x < width; x++) \ d[x] = (type) color; \ break; \} switch(bpp) { case 1: COLORFILL_ROW(BYTE) case 2: COLORFILL_ROW(WORD) case 3: { BYTE *d = (BYTE *) buf; for (x = 0; x < width; x++,d+=3) { d[0] = (color ) & 0xFF; d[1] = (color>> 8) & 0xFF; d[2] = (color>>16) & 0xFF; } break;} case 4: COLORFILL_ROW(DWORD) default: FIXME("Color fill not implemented for bpp %d!\n", bpp*8); return DDERR_UNSUPPORTED; }#undef COLORFILL_ROW /* Now copy first row */ first = buf; for (y = 1; y < height; y++) { buf += lPitch; memcpy(buf, first, width * bpp); } return DD_OK;}HRESULT WINAPIDIB_DirectDrawSurface_Blt(LPDIRECTDRAWSURFACE7 iface, LPRECT rdst, LPDIRECTDRAWSURFACE7 src, LPRECT rsrc, DWORD dwFlags, LPDDBLTFX lpbltfx){ ICOM_THIS(IDirectDrawSurfaceImpl,iface); RECT xdst,xsrc; DDSURFACEDESC2 ddesc,sdesc; HRESULT ret = DD_OK; int bpp, srcheight, srcwidth, dstheight, dstwidth, width; int x, y; LPBYTE dbuf, sbuf; TRACE("(%p)->(%p,%p,%p,%08lx,%p)\n", This,rdst,src,rsrc,dwFlags,lpbltfx); if (TRACE_ON(ddraw)) { if (rdst) TRACE("\tdestrect :%ldx%ld-%ldx%ld\n",rdst->left,rdst->top,rdst->right,rdst->bottom); if (rsrc) TRACE("\tsrcrect :%ldx%ld-%ldx%ld\n",rsrc->left,rsrc->top,rsrc->right,rsrc->bottom); TRACE("\tflags: "); DDRAW_dump_DDBLT(dwFlags); if (dwFlags & DDBLT_DDFX) { TRACE("\tblitfx: "); DDRAW_dump_DDBLTFX(lpbltfx->dwDDFX); } } /* First, check if the possible override function handles this case */ if (This->aux_blt != NULL) { if (This->aux_blt(This, rdst, src, rsrc, dwFlags, lpbltfx) == DD_OK) return DD_OK; } DD_STRUCT_INIT(&ddesc); DD_STRUCT_INIT(&sdesc); sdesc.dwSize = sizeof(sdesc); if (src) IDirectDrawSurface7_Lock(src, NULL, &sdesc, DDLOCK_READONLY, 0); ddesc.dwSize = sizeof(ddesc); IDirectDrawSurface7_Lock(iface,NULL,&ddesc,DDLOCK_WRITEONLY,0); if (rdst) { memcpy(&xdst,rdst,sizeof(xdst)); } else { xdst.top = 0; xdst.bottom = ddesc.dwHeight; xdst.left = 0; xdst.right = ddesc.dwWidth; } if (rsrc) { memcpy(&xsrc,rsrc,sizeof(xsrc)); } else { if (src) { xsrc.top = 0; xsrc.bottom = sdesc.dwHeight;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -