| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931 |
- /*
- ** Command & Conquer Generals Zero Hour(tm)
- ** Copyright 2025 Electronic Arts Inc.
- **
- ** This program is free software: you can redistribute it and/or modify
- ** it under the terms of the GNU General Public License as published by
- ** the Free Software Foundation, either version 3 of the License, or
- ** (at your option) any later version.
- **
- ** This program 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 General Public License for more details.
- **
- ** You should have received a copy of the GNU General Public License
- ** along with this program. If not, see <http://www.gnu.org/licenses/>.
- */
- /***********************************************************************************************
- *** C O N F I D E N T I A L --- W E S T W O O D S T U D I O S ***
- ***********************************************************************************************
- * *
- * Project Name : Command & Conquer *
- * *
- * $Archive:: /G/wwlib/dsurface.cpp $*
- * *
- * $Author:: Neal_k $*
- * *
- * $Modtime:: 6/23/00 2:26p $*
- * *
- * $Revision:: 2 $*
- * *
- *---------------------------------------------------------------------------------------------*
- * Functions: *
- * DSurface::Blit_From -- Blit from one surface to this one. *
- * DSurface::Blit_From -- Blit graphic memory from one rectangle to another. *
- * DSurface::Build_Hicolor_Pixel -- Construct a hicolor pixel according to the surface pixel *
- * DSurface::Build_Remap_Table -- Build a highcolor remap table. *
- * DSurface::Bytes_Per_Pixel -- Fetches the bytes per pixel of the surface. *
- * DSurface::Create_Primary -- Creates a primary (visible) surface. *
- * DSurface::DSurface -- Create a surface attached to specified DDraw Surface Object. *
- * DSurface::DSurface -- Default constructor for surface object. *
- * DSurface::DSurface -- Off screen direct draw surface constructor. *
- * DSurface::Fill_Rect -- Fills a rectangle with clipping control. *
- * DSurface::Fill_Rect -- This routine will fill the specified rectangle. *
- * DSurface::Lock -- Fetches a working pointer into surface memory. *
- * DSurface::Restore_Check -- Checks for and restores surface memory if necessary. *
- * DSurface::Stride -- Fetches the bytes between rows. *
- * DSurface::Unlock -- Unlock a previously locked surface. *
- * DSurface::~DSurface -- Destructor for a direct draw surface object. *
- * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
- #include "always.h"
- #include "dsurface.h"
- #include <assert.h>
- extern LPDIRECTDRAW DirectDrawObject; //pointer to direct draw object
- extern LPDIRECTDRAWSURFACE PaletteSurface;
- /*
- ** Clipper object (for primary surface).
- */
- LPDIRECTDRAWCLIPPER DSurface::Clipper = NULL;
- int DSurface::RedRight = 0;
- int DSurface::RedLeft = 0;
- int DSurface::BlueRight = 0;
- int DSurface::BlueLeft = 0;
- int DSurface::GreenRight = 0;
- int DSurface::GreenLeft = 0;
- unsigned short DSurface::HalfbrightMask = 0;
- unsigned short DSurface::QuarterbrightMask = 0;
- unsigned short DSurface::EighthbrightMask = 0;
- DDPIXELFORMAT DSurface::PixelFormat;
- /***********************************************************************************************
- * DSurface::DSurface -- Off screen direct draw surface constructor. *
- * *
- * This constructor will create a Direct Draw enabled surface in video memory if possible. *
- * Such a surface will be able to use hardware assist if possible. The surface created *
- * is NOT visible. It only exists as a work surface and cannot be flipped to the visible *
- * surface. It can only be blitted to the visible surface. *
- * *
- * INPUT: width -- The width of the surface to create. *
- * *
- * height -- The height of the surface to create. *
- * *
- * OUTPUT: none *
- * *
- * WARNINGS: The surface pixel format is the same as that of the visible display mode. It *
- * is important to construct surfaces using this routine, only AFTER the display *
- * mode has been set. *
- * *
- * HISTORY: *
- * 02/07/1997 JLB : Created. *
- *=============================================================================================*/
- DSurface::DSurface(int width, int height, bool system_memory, DDPIXELFORMAT *pixform) :
- XSurface(width, height),
- BytesPerPixel(0),
- LockPtr(NULL),
- IsPrimary(false),
- IsVideoRam(false),
- SurfacePtr(NULL),
- Description(NULL),
- DCUnlockCount(0)
- {
- Description = W3DNEW DDSURFACEDESC;
- if (Description != NULL) {
- memset(Description, '\0', sizeof(DDSURFACEDESC));
- Description->dwSize = sizeof(DDSURFACEDESC);
- Description->dwFlags = DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH;
- Description->dwWidth = width;
- Description->dwHeight = height;
- Description->ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
- if (system_memory == true)
- Description->ddsCaps.dwCaps |= DDSCAPS_SYSTEMMEMORY;
- /*
- ** Was a custom (non-display-depth) pixel format specified?
- */
- if (pixform)
- {
- Description->ddpfPixelFormat=*pixform;
- Description->dwFlags |= DDSD_PIXELFORMAT;
- }
- DirectDrawObject->CreateSurface(Description, &SurfacePtr, NULL);
- /*
- ** Get a description of the surface that was just allocated.
- */
- if (SurfacePtr != NULL) {
- memset(Description, '\0', sizeof(DDSURFACEDESC));
- Description->dwSize = sizeof(DDSURFACEDESC);
- SurfacePtr->GetSurfaceDesc(Description);
- BytesPerPixel = (Description->ddpfPixelFormat.dwRGBBitCount+7)/8;
- IsVideoRam = ((Description->ddsCaps.dwCaps & DDSCAPS_VIDEOMEMORY) != 0);
- /*
- ** If this is a hicolor surface, then build the shift values for
- ** building and extracting the colors from the hicolor pixel.
- */
- if (BytesPerPixel == 2) {
- int index;
- int shift = Description->ddpfPixelFormat.dwRBitMask;
- ThisRedRight = 0;
- ThisRedLeft = 0;
- for (index = 0; index < 16; index++) {
- if (shift & 0x01) break;
- shift >>= 1;
- ThisRedRight++;
- }
- for (index = 0; index < 8; index++) {
- if (shift & 0x80) break;
- shift <<= 1;
- ThisRedLeft++;
- }
- shift = Description->ddpfPixelFormat.dwGBitMask;
- ThisGreenRight = 0;
- ThisGreenLeft = 0;
- for (index = 0; index < 16; index++) {
- if (shift & 0x01) break;
- ThisGreenRight++;
- shift >>= 1;
- }
- for (index = 0; index < 8; index++) {
- if (shift & 0x80) break;
- ThisGreenLeft++;
- shift <<= 1;
- }
- shift = Description->ddpfPixelFormat.dwBBitMask;
- ThisBlueRight = 0;
- ThisBlueLeft = 0;
- for (index = 0; index < 16; index++) {
- if (shift & 0x01) break;
- ThisBlueRight++;
- shift >>= 1;
- }
- for (index = 0; index < 8; index++) {
- if (shift & 0x80) break;
- ThisBlueLeft++;
- shift <<= 1;
- }
- }
- }
- }
- }
- /***********************************************************************************************
- * DSurface::~DSurface -- Destructor for a direct draw surface object. *
- * *
- * This will destruct (make invalid) the direct draw surface. *
- * *
- * INPUT: none *
- * *
- * OUTPUT: none *
- * *
- * WARNINGS: none *
- * *
- * HISTORY: *
- * 02/07/1997 JLB : Created. *
- *=============================================================================================*/
- DSurface::~DSurface(void)
- {
- /*
- ** If this is the primary surface, then the clipper must be detached from
- ** this surface and the clipper object deleted.
- */
- if (IsPrimary && SurfacePtr != NULL && Clipper != NULL) {
- SurfacePtr->SetClipper(NULL);
- Clipper->Release();
- Clipper = NULL;
- }
- /*
- ** Delete the description of the surface.
- */
- delete Description;
- Description = NULL;
- if (SurfacePtr != NULL) {
- SurfacePtr->Release();
- }
- SurfacePtr = NULL;
- }
- /***********************************************************************************************
- * DSurface::DSurface -- Default constructor for surface object. *
- * *
- * This default constructor for a surface object should not be used. Although it properly *
- * creates a non-functional surface, there is no use for such a surface. This default *
- * constructor is provided for those rare cases where symatics require a default *
- * constructor. *
- * *
- * INPUT: none *
- * *
- * OUTPUT: none *
- * *
- * WARNINGS: none *
- * *
- * HISTORY: *
- * 02/07/1997 JLB : Created. *
- *=============================================================================================*/
- DSurface::DSurface(void) :
- BytesPerPixel(0),
- LockPtr(NULL),
- SurfacePtr(NULL),
- Description(NULL),
- DCUnlockCount(0)
- {
- Description = W3DNEW DDSURFACEDESC;
- memset(Description, '\0', sizeof(DDSURFACEDESC));
- Description->dwSize = sizeof(DDSURFACEDESC);
- }
- /***********************************************************************************************
- * DSurface::GetDC -- Get the windows device context from our surface *
- * *
- * INPUT: none *
- * *
- * OUTPUT: none *
- * *
- * WARNINGS: Any current locks will get unlocked while the DC is held *
- * *
- * HISTORY: *
- * 06/21/2000 NAK : Created. *
- *=============================================================================================*/
- HDC DSurface::GetDC(void)
- {
- HDC hdc = NULL;
- HRESULT hr;
- // We have to remove all current locks to get the device context unfortunately...
- while (LockCount) {
- Unlock();
- DCUnlockCount++;
- }
- hr = SurfacePtr->GetDC(&hdc);
- if (hr != DD_OK)
- {
- while(DCUnlockCount) // restore the lock state
- {
- Lock();
- DCUnlockCount--;
- }
- return(NULL);
- }
- // GetDC() locks the surface internally, so we need to reflect that here
- if (hr == DD_OK) {
- LockCount++;
- }else{
- hdc = NULL;
- }
- return (hdc);
- }
- /***********************************************************************************************
- * DSurface::ReleaseDC -- Release the windows device context from our surface *
- * *
- * INPUT: none *
- * *
- * OUTPUT: none *
- * *
- * WARNINGS: Restores any locks held before the call to GetDC() *
- * *
- * HISTORY: *
- * 06/21/2000 NAK : Created. *
- *=============================================================================================*/
- int DSurface::ReleaseDC(HDC hdc)
- {
- HRESULT hr;
- hr = SurfacePtr->ReleaseDC(hdc);
- assert(hr == DD_OK);
- // ReleaseDC() unlocks the surface internally, so we need to reflect that here.
- if ((hr == DD_OK) && (LockCount > 0)) {
- LockCount--;
- }
- while(DCUnlockCount) // restore the lock state
- {
- Lock();
- DCUnlockCount--;
- }
- return (1);
- }
- /***********************************************************************************************
- * DSurface::Create_Primary -- Creates a primary (visible) surface. *
- * *
- * This routine is used to create the surface object that represents the currently *
- * visible display. The surface is not allocated, it is merely linked to the preexisting *
- * surface that the Windows GDI is also currently using. *
- * *
- * INPUT: backsurface -- Optional pointer to specify where the backpage (flip enabled) *
- * pointer will be placed. If this parameter is NULL, then no *
- * back surface will be created. *
- * *
- * OUTPUT: Returns with a pointer to the primary surface. *
- * *
- * WARNINGS: There can be only one primary surface. If an additional call to this routine *
- * is made, another surface pointer will be returned, but it will point to the *
- * same surface as before. *
- * *
- * HISTORY: *
- * 02/07/1997 JLB : Created. *
- *=============================================================================================*/
- DSurface * DSurface::Create_Primary(DSurface ** backsurface1)
- {
- DSurface * surface = W3DNEW DSurface();
- int backcount = (backsurface1 != NULL) ? 1 : 0;
- /*
- ** Setup parameter for creating the primary surface. This will
- ** always be the visible surface plus optional back buffers of identical
- ** dimensions.
- */
- surface->Description->dwFlags = DDSD_CAPS;
- surface->Description->ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
- if (backcount > 0) {
- surface->Description->ddsCaps.dwCaps |= DDSCAPS_FLIP | DDSCAPS_COMPLEX;
- surface->Description->dwFlags |= DDSD_BACKBUFFERCOUNT;
- surface->Description->dwBackBufferCount = backcount;
- }
- HRESULT result = DirectDrawObject->CreateSurface(surface->Description, &surface->SurfacePtr, NULL);
- /*
- ** If the primary surface object was created, then fetch a pointer to the
- ** back buffer if there is one present.
- */
- if (result == DD_OK) {
- if (backcount > 0) {
- LPDIRECTDRAWSURFACE back;
- DDSCAPS caps;
- caps.dwCaps = DDSCAPS_BACKBUFFER;
- result = surface->SurfacePtr->GetAttachedSurface(&caps, &back);
- if (result == DD_OK) {
- *backsurface1 = W3DNEW DSurface(back);
- }
- }
- /*
- ** Get a description of the surface that was just allocated.
- */
- memset(surface->Description, '\0', sizeof(DDSURFACEDESC));
- surface->Description->dwSize = sizeof(DDSURFACEDESC);
- surface->SurfacePtr->GetSurfaceDesc(surface->Description);
- surface->BytesPerPixel = (surface->Description->ddpfPixelFormat.dwRGBBitCount+7)/8;
- surface->IsPrimary = true;
- // surface->Window.Set(Rect(0, 0, surface->Description->dwWidth, surface->Description->dwHeight));
- surface->Width = surface->Description->dwWidth;
- surface->Height = surface->Description->dwHeight;
- PaletteSurface = surface->SurfacePtr;
- /*
- ** Attach a clipper object to the surface so that it can cooperate
- ** with the system GDI. This only comes into play if there are going
- ** to be GDI graphical elements on top of the surface (normally this
- ** isn't the case for full screen games). It doesn't hurt to attach
- ** a clipper object anyway -- just in case.
- */
- if (DirectDrawObject->CreateClipper(0, &Clipper, NULL) == DD_OK) {
- if (Clipper->SetHWnd(0, GetActiveWindow()) == DD_OK) {
- surface->SurfacePtr->SetClipper(Clipper);
- }
- }
- /*
- ** Fetch the pixel format for the surface.
- */
- memcpy(&PixelFormat, &surface->Description->ddpfPixelFormat, sizeof(DDPIXELFORMAT));
- /*
- ** If this is a hicolor surface, then build the shift values for
- ** building and extracting the colors from the hicolor pixel.
- */
- if (surface->Bytes_Per_Pixel() == 2) {
- int index;
- int shift = PixelFormat.dwRBitMask;
- RedRight = 0;
- RedLeft = 0;
- for (index = 0; index < 16; index++) {
- if (shift & 0x01) break;
- shift >>= 1;
- RedRight++;
- }
- for (index = 0; index < 8; index++) {
- if (shift & 0x80) break;
- shift <<= 1;
- RedLeft++;
- }
- shift = PixelFormat.dwGBitMask;
- GreenRight = 0;
- GreenLeft = 0;
- for (index = 0; index < 16; index++) {
- if (shift & 0x01) break;
- GreenRight++;
- shift >>= 1;
- }
- for (index = 0; index < 8; index++) {
- if (shift & 0x80) break;
- GreenLeft++;
- shift <<= 1;
- }
- shift = PixelFormat.dwBBitMask;
- BlueRight = 0;
- BlueLeft = 0;
- for (index = 0; index < 16; index++) {
- if (shift & 0x01) break;
- BlueRight++;
- shift >>= 1;
- }
- for (index = 0; index < 8; index++) {
- if (shift & 0x80) break;
- BlueLeft++;
- shift <<= 1;
- }
- /*
- ** Create the halfbright mask.
- */
- HalfbrightMask = (unsigned short)Build_Hicolor_Pixel(127, 127, 127);
- QuarterbrightMask = (unsigned short)Build_Hicolor_Pixel(63, 63, 63);
- EighthbrightMask = (unsigned short)Build_Hicolor_Pixel(31, 31, 31);
- }
- } else {
- delete surface;
- surface = NULL;
- }
- return(surface);
- }
- /***********************************************************************************************
- * DSurface::DSurface -- Create a surface attached to specified DDraw Surface Object. *
- * *
- * If an existing Direct Draw Surface Object is available, use this constructor to create *
- * a DSurface object that is attached to the surface specified. *
- * *
- * INPUT: surfaceptr -- Pointer to a preexisting Direct Draw Surface Object. *
- * *
- * OUTPUT: none *
- * *
- * WARNINGS: none *
- * *
- * HISTORY: *
- * 02/07/1997 JLB : Created. *
- *=============================================================================================*/
- DSurface::DSurface(LPDIRECTDRAWSURFACE surfaceptr) :
- BytesPerPixel(0),
- LockPtr(NULL),
- SurfacePtr(surfaceptr),
- Description(NULL)
- {
- if (SurfacePtr != NULL) {
- Description = W3DNEW DDSURFACEDESC;
- memset(Description, '\0', sizeof(DDSURFACEDESC));
- Description->dwSize = sizeof(DDSURFACEDESC);
- HRESULT result = SurfacePtr->GetSurfaceDesc(Description);
- if (result == DD_OK) {
- BytesPerPixel = (Description->ddpfPixelFormat.dwRGBBitCount+7)/8;
- // Window.Set(Rect(0, 0, Description->dwWidth, Description->dwHeight));
- Width = Description->dwWidth;
- Height = Description->dwHeight;
- }
- }
- }
- /***********************************************************************************************
- * DSurface::Bytes_Per_Pixel -- Fetches the bytes per pixel of the surface. *
- * *
- * This routine will return with the number of bytes that each pixel consumes. The value *
- * is dependant upon the graphic mode of the display. *
- * *
- * INPUT: none *
- * *
- * OUTPUT: Returns with the bytes per pixel of the surface object. *
- * *
- * WARNINGS: none *
- * *
- * HISTORY: *
- * 02/07/1997 JLB : Created. *
- *=============================================================================================*/
- int DSurface::Bytes_Per_Pixel(void) const
- {
- return(BytesPerPixel);
- }
- /***********************************************************************************************
- * DSurface::Stride -- Fetches the bytes between rows. *
- * *
- * This routine will return the number of bytes to add so that the pointer will be *
- * positioned at the same column, but one row down the screen. This value may very well *
- * NOT be equal to the width multiplied by the bytes per pixel. *
- * *
- * INPUT: none *
- * *
- * OUTPUT: Returns with the byte difference between subsequent pixel rows. *
- * *
- * WARNINGS: none *
- * *
- * HISTORY: *
- * 02/07/1997 JLB : Created. *
- *=============================================================================================*/
- int DSurface::Stride(void) const
- {
- return(Description->lPitch);
- }
- /***********************************************************************************************
- * DSurface::Lock -- Fetches a working pointer into surface memory. *
- * *
- * This routine will return with a pointer to the pixel at the location specified. In order *
- * to directly manipulate surface memory, the surface memory must be mapped into the *
- * program's logical address space. In addition, all blitter activity on the surface will *
- * be suspended. Every call to Lock must be have a corresponding call to Unlock if the *
- * pointer returned is not equal to NULL. *
- * *
- * INPUT: point -- Pixel coordinate to return a pointer to. *
- * *
- * OUTPUT: Returns with a pointer to the pixel specified. If the return value is NULL, then *
- * the surface could not be locked and no call to Unlock should be performed. *
- * *
- * WARNINGS: It is important not to keep a surface locked indefinately since the blitter *
- * will not be able to function. Due to the time that locking consumes, it is *
- * also important to not perform unnecessarily frequent Lock calls. *
- * *
- * HISTORY: *
- * 02/07/1997 JLB : Created. *
- *=============================================================================================*/
- void * DSurface::Lock(Point2D point) const
- {
- Restore_Check();
- if (LockCount == 0) {
- DDSURFACEDESC desc;
- memset(&desc, '\0', sizeof(desc));
- desc.dwSize = sizeof(desc);
- HRESULT result = SurfacePtr->Lock(NULL, &desc, DDLOCK_SURFACEMEMORYPTR|DDLOCK_WAIT, NULL);
- if (result != DD_OK) return(NULL);
- memcpy(Description, &desc, sizeof(DDSURFACEDESC));
- BytesPerPixel = (Description->ddpfPixelFormat.dwRGBBitCount+7)/8;
- LockPtr = Description->lpSurface;
- }
- XSurface::Lock();
- return(((char*)LockPtr) + point.Y * Stride() + point.X * Bytes_Per_Pixel());
- }
- /***********************************************************************************************
- * DSurface::Unlock -- Unlock a previously locked surface. *
- * *
- * After a surface has been successfully locked, a call to the Unlock() function is *
- * required. *
- * *
- * INPUT: none *
- * *
- * OUTPUT: bool; Was the unlock successful? *
- * *
- * WARNINGS: Only pair a call to Unlock if the prior Lock actually returned a non-NULL *
- * value. *
- * *
- * HISTORY: *
- * 02/07/1997 JLB : Created. *
- *=============================================================================================*/
- bool DSurface::Unlock(void) const
- {
- Restore_Check();
- if (LockCount > 0) {
- XSurface::Unlock();
- if (LockCount == 0) {
- SurfacePtr->Unlock(LockPtr);
- LockPtr = NULL;
- }
- return(true);
- }
- return(false);
- }
- /***********************************************************************************************
- * DSurface::Restore_Check -- Checks for and restores surface memory if necessary. *
- * *
- * This routine will check to see if surface memory has been lost to the surface. If it *
- * has, then the surface memory will be restored. *
- * *
- * INPUT: none *
- * *
- * OUTPUT: none *
- * *
- * WARNINGS: none *
- * *
- * HISTORY: *
- * 02/07/1997 JLB : Created. *
- *=============================================================================================*/
- void DSurface::Restore_Check(void) const
- {
- if (SurfacePtr->IsLost() == DDERR_SURFACELOST) {
- SurfacePtr->Restore();
- if (LockCount > 0 && SurfacePtr->IsLost() != DDERR_SURFACELOST) {
- int oldlockcount = LockCount;
- LockCount = 0;
- Lock();
- LockCount++;
- Unlock();
- LockCount = oldlockcount;
- }
- }
- }
- /***********************************************************************************************
- * DSurface::Blit_From -- Blit graphic memory from one rectangle to another. *
- * *
- * This routine will use the blitter (if possible) to blit a block of graphic memory from *
- * one screen rectangle to another. If the rectangles do no match in size, scaling may *
- * be performed. *
- * *
- * INPUT: destrect -- The destination rectangle. *
- * *
- * ssource -- The source surface to blit from. *
- * *
- * sourecrect -- The source rectangle. *
- * *
- * trans -- Should transparency checking be performed? *
- * *
- * OUTPUT: bool; Was the blit performed without error? *
- * *
- * WARNINGS: none *
- * *
- * HISTORY: *
- * 02/07/1997 JLB : Created. *
- *=============================================================================================*/
- bool DSurface::Blit_From(Rect const & destrect, Surface const & ssource, Rect const & sourcerect, bool trans)
- {
- return(Blit_From(Get_Rect(), destrect, ssource, ssource.Get_Rect(), sourcerect, trans));
- }
- /***********************************************************************************************
- * DSurface::Blit_From -- Blit from one surface to this one. *
- * *
- * Use this routine to blit a rectangle from the specified surface to this surface while *
- * performing clipping upon the blit rectangles specified. *
- * *
- * INPUT: dcliprect -- The clipping rectangle to use for this surface. *
- * *
- * destrect -- The destination rectangle of the blit. The is relative to the *
- * dcliprect parameter. *
- * *
- * ssource -- The source surface of the blit. *
- * *
- * scliprect -- The source clipping rectangle. *
- * *
- * sourcrect -- The source rectangle of the blit. This rectangle is relative to *
- * the source clipping rectangle. *
- * *
- * trans -- Is this a transparent blit request? *
- * *
- * OUTPUT: bool; Was there a blit performed? A 'false' return value would indicate that the *
- * blit was clipped into nothing. *
- * *
- * WARNINGS: none *
- * *
- * HISTORY: *
- * 05/27/1997 JLB : Created. *
- *=============================================================================================*/
- bool DSurface::Blit_From(Rect const & dcliprect, Rect const & destrect, Surface const & ssource, Rect const & scliprect, Rect const & sourcerect, bool trans)
- {
- if (!dcliprect.Is_Valid() || !scliprect.Is_Valid() || !destrect.Is_Valid() || !sourcerect.Is_Valid()) return(false);
- /*
- ** For non-direct draw surfaces, perform a manual blit operation. This is also
- ** necessary if any of the surfaces are currently locked. It is also necessary if the
- ** blit regions overlap and the blitter cannot handle overlapped regions.
- **
- ** NOTE: Its legal to blit to a locked surface but not from a locked surface.
- ** ST - 4/23/97 1:03AM
- */
- if (!ssource.Is_Direct_Draw() || ((DSurface&)ssource).Is_Locked() || trans || Bytes_Per_Pixel() != ssource.Bytes_Per_Pixel()) {
- return(XSurface::Blit_From(destrect, ssource, sourcerect, trans));
- }
- Restore_Check();
- DSurface const & source = (DSurface const &)ssource;
- Rect drect = destrect;
- Rect srect = sourcerect;
- Rect swindow = scliprect.Intersect(ssource.Get_Rect());
- Rect dwindow = dcliprect.Intersect(Get_Rect());
- if (Blit_Clip(drect, dwindow, srect, swindow)) {
- RECT xdestrect;
- xdestrect.left = drect.X+dwindow.X;
- xdestrect.top = drect.Y+dwindow.Y;
- xdestrect.right = drect.X+dwindow.X+drect.Width;
- xdestrect.bottom = drect.Y+dwindow.Y+drect.Height;
- RECT xsrcrect;
- xsrcrect.left = srect.X+swindow.X;
- xsrcrect.top = srect.Y+swindow.Y;
- xsrcrect.right = srect.X+swindow.X+srect.Width;
- xsrcrect.bottom = srect.Y+swindow.Y+srect.Height;
- HRESULT result = SurfacePtr->Blt(&xdestrect, source.SurfacePtr, &xsrcrect, DDBLT_WAIT, NULL);
- return(result == DD_OK);
- }
- return(false);
- }
- /***********************************************************************************************
- * DSurface::Fill_Rect -- This routine will fill the specified rectangle. *
- * *
- * This routine will fill the specified rectangle with a color. *
- * *
- * INPUT: fillrect -- The rectangle to fill. *
- * *
- * color -- The color to fill with. *
- * *
- * OUTPUT: bool; Was the fill performed without error? *
- * *
- * WARNINGS: none *
- * *
- * HISTORY: *
- * 02/07/1997 JLB : Created. *
- *=============================================================================================*/
- bool DSurface::Fill_Rect(Rect const & fillrect, int color)
- {
- return(DSurface::Fill_Rect(Get_Rect(), fillrect, color));
- }
- /***********************************************************************************************
- * DSurface::Fill_Rect -- Fills a rectangle with clipping control. *
- * *
- * This routine will fill a rectangle on this surface, but will clip the request against *
- * a clipping rectangle first. *
- * *
- * INPUT: cliprect -- The clipping rectangle to use for this surface. *
- * *
- * fillrect -- The rectangle to fill with the specified color. The rectangle is *
- * relative to the clipping rectangle. *
- * *
- * color -- The color (surface dependant format) to use when filling the rectangle *
- * pixels. *
- * *
- * OUTPUT: bool; Was a fill operation performed? A 'false' return value would mean that the *
- * fill request was clipped into nothing. *
- * *
- * WARNINGS: none *
- * *
- * HISTORY: *
- * 05/27/1997 JLB : Created. *
- *=============================================================================================*/
- bool DSurface::Fill_Rect(Rect const & cliprect, Rect const & fillrect, int color)
- {
- if (!fillrect.Is_Valid()) return(false);
-
- /*
- ** If the buffer is locked, then using the blitter to perform the fill is not possible.
- ** In such a case, perform a manual fill of the region.
- */
- if (Is_Locked()) {
- return(XSurface::Fill_Rect(cliprect, fillrect, color));
- }
- Restore_Check();
- /*
- ** Ensure that the clipping rectangle is legal.
- */
- Rect crect = cliprect.Intersect(Get_Rect());
- /*
- ** Bias the fill rect to the clipping rectangle.
- */
- Rect frect = fillrect.Bias_To(cliprect);
- /*
- ** Find the region that should be filled after being clipped by the
- ** clipping rectangle. This could result in no fill operation being performed
- ** if the desired fill rectangle has been completely clipped away.
- */
- frect = frect.Intersect(crect);
- if (!frect.Is_Valid()) return(false);
- RECT rect;
- rect.left = frect.X;
- rect.top = frect.Y;
- rect.right = rect.left + frect.Width;
- rect.bottom = rect.top + frect.Height;
- DDBLTFX fx;
- memset(&fx, '\0', sizeof(fx));
- fx.dwSize = sizeof(fx);
- fx.dwFillColor = color;
- HRESULT result = SurfacePtr->Blt(&rect, NULL, NULL, DDBLT_WAIT|DDBLT_COLORFILL, &fx);
- return(result == DD_OK);
- }
- /***********************************************************************************************
- * DSurface::Build_Hicolor_Pixel -- Construct a hicolor pixel according to the surface pixel f *
- * *
- * This routine will construct a pixel according to the highcolor pixel format for this *
- * surface. *
- * *
- * INPUT: red -- The red component of the color (0..255). *
- * *
- * green -- The green component of the color (0..255). *
- * *
- * blue -- The blue component of the color (0..255). *
- * *
- * OUTPUT: Returns with a screen format pixel number that most closesly matches the color *
- * specified. *
- * *
- * WARNINGS: The return value is card dependant and only applies to hicolor displays. *
- * *
- * HISTORY: *
- * 05/27/1997 JLB : Created. *
- *=============================================================================================*/
- int DSurface::Build_Hicolor_Pixel(int red, int green, int blue)
- {
- return(((red >> RedLeft) << RedRight) | ((green >> GreenLeft) << GreenRight) | ((blue >> BlueLeft) << BlueRight));
- }
- /***********************************************************************************************
- * DSurface::Build_Remap_Table -- Build a highcolor remap table. *
- * *
- * This will build a complete hicolor remap table for the palette specified. This table *
- * can then be used to quickly fetch a pixel that matches the color index of the palette. *
- * *
- * INPUT: table -- The location to store the hicolor table. The buffer must be 256*2 bytes *
- * long. *
- * *
- * palette -- The palette to use to create the remap table. *
- * *
- * OUTPUT: none *
- * *
- * WARNINGS: none *
- * *
- * HISTORY: *
- * 05/27/1997 JLB : Created. *
- *=============================================================================================*/
- void DSurface::Build_Remap_Table(unsigned short * table, PaletteClass const & palette)
- {
- assert(table != NULL);
- /*
- ** Build the hicolor index table according to the palette.
- */
- for (int index = 0; index < 256; index++) {
- table[index] = (unsigned short)Build_Hicolor_Pixel(palette[index].Get_Red(), palette[index].Get_Green(), palette[index].Get_Blue());
- }
- }
|