Richard Boegli's CnC_Generals_Zero_Hour Fork WIP
This is documentation of Richard Boegil's Zero Hour Fork
 
Loading...
Searching...
No Matches
dsurface.cpp
Go to the documentation of this file.
1/*
2** Command & Conquer Generals Zero Hour(tm)
3** Copyright 2025 Electronic Arts Inc.
4**
5** This program is free software: you can redistribute it and/or modify
6** it under the terms of the GNU General Public License as published by
7** the Free Software Foundation, either version 3 of the License, or
8** (at your option) any later version.
9**
10** This program is distributed in the hope that it will be useful,
11** but WITHOUT ANY WARRANTY; without even the implied warranty of
12** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13** GNU General Public License for more details.
14**
15** You should have received a copy of the GNU General Public License
16** along with this program. If not, see <http://www.gnu.org/licenses/>.
17*/
18
19/***********************************************************************************************
20 *** 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 ***
21 ***********************************************************************************************
22 * *
23 * Project Name : Command & Conquer *
24 * *
25 * $Archive:: /G/wwlib/dsurface.cpp $*
26 * *
27 * $Author:: Neal_k $*
28 * *
29 * $Modtime:: 6/23/00 2:26p $*
30 * *
31 * $Revision:: 2 $*
32 * *
33 *---------------------------------------------------------------------------------------------*
34 * Functions: *
35 * DSurface::Blit_From -- Blit from one surface to this one. *
36 * DSurface::Blit_From -- Blit graphic memory from one rectangle to another. *
37 * DSurface::Build_Hicolor_Pixel -- Construct a hicolor pixel according to the surface pixel *
38 * DSurface::Build_Remap_Table -- Build a highcolor remap table. *
39 * DSurface::Bytes_Per_Pixel -- Fetches the bytes per pixel of the surface. *
40 * DSurface::Create_Primary -- Creates a primary (visible) surface. *
41 * DSurface::DSurface -- Create a surface attached to specified DDraw Surface Object. *
42 * DSurface::DSurface -- Default constructor for surface object. *
43 * DSurface::DSurface -- Off screen direct draw surface constructor. *
44 * DSurface::Fill_Rect -- Fills a rectangle with clipping control. *
45 * DSurface::Fill_Rect -- This routine will fill the specified rectangle. *
46 * DSurface::Lock -- Fetches a working pointer into surface memory. *
47 * DSurface::Restore_Check -- Checks for and restores surface memory if necessary. *
48 * DSurface::Stride -- Fetches the bytes between rows. *
49 * DSurface::Unlock -- Unlock a previously locked surface. *
50 * DSurface::~DSurface -- Destructor for a direct draw surface object. *
51 * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
52
53#include "always.h"
54#include "dsurface.h"
55#include <assert.h>
56
57extern LPDIRECTDRAW DirectDrawObject; //pointer to direct draw object
58extern LPDIRECTDRAWSURFACE PaletteSurface;
59
60/*
61** Clipper object (for primary surface).
62*/
63LPDIRECTDRAWCLIPPER DSurface::Clipper = NULL;
64
65int DSurface::RedRight = 0;
66int DSurface::RedLeft = 0;
68int DSurface::BlueLeft = 0;
71
72unsigned short DSurface::HalfbrightMask = 0;
73unsigned short DSurface::QuarterbrightMask = 0;
74unsigned short DSurface::EighthbrightMask = 0;
75
76DDPIXELFORMAT DSurface::PixelFormat;
77
78
79/***********************************************************************************************
80 * DSurface::DSurface -- Off screen direct draw surface constructor. *
81 * *
82 * This constructor will create a Direct Draw enabled surface in video memory if possible. *
83 * Such a surface will be able to use hardware assist if possible. The surface created *
84 * is NOT visible. It only exists as a work surface and cannot be flipped to the visible *
85 * surface. It can only be blitted to the visible surface. *
86 * *
87 * INPUT: width -- The width of the surface to create. *
88 * *
89 * height -- The height of the surface to create. *
90 * *
91 * OUTPUT: none *
92 * *
93 * WARNINGS: The surface pixel format is the same as that of the visible display mode. It *
94 * is important to construct surfaces using this routine, only AFTER the display *
95 * mode has been set. *
96 * *
97 * HISTORY: *
98 * 02/07/1997 JLB : Created. *
99 *=============================================================================================*/
100DSurface::DSurface(int width, int height, bool system_memory, DDPIXELFORMAT *pixform) :
101 XSurface(width, height),
102 BytesPerPixel(0),
103 LockPtr(NULL),
109{
110 Description = W3DNEW DDSURFACEDESC;
111 if (Description != NULL) {
112 memset(Description, '\0', sizeof(DDSURFACEDESC));
113 Description->dwSize = sizeof(DDSURFACEDESC);
114 Description->dwFlags = DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH;
115 Description->dwWidth = width;
116 Description->dwHeight = height;
117
118 Description->ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
119
120 if (system_memory == true)
121 Description->ddsCaps.dwCaps |= DDSCAPS_SYSTEMMEMORY;
122
123 /*
124 ** Was a custom (non-display-depth) pixel format specified?
125 */
126 if (pixform)
127 {
128 Description->ddpfPixelFormat=*pixform;
129 Description->dwFlags |= DDSD_PIXELFORMAT;
130 }
131
132
133 DirectDrawObject->CreateSurface(Description, &SurfacePtr, NULL);
134
135 /*
136 ** Get a description of the surface that was just allocated.
137 */
138 if (SurfacePtr != NULL) {
139 memset(Description, '\0', sizeof(DDSURFACEDESC));
140 Description->dwSize = sizeof(DDSURFACEDESC);
141 SurfacePtr->GetSurfaceDesc(Description);
142 BytesPerPixel = (Description->ddpfPixelFormat.dwRGBBitCount+7)/8;
143 IsVideoRam = ((Description->ddsCaps.dwCaps & DDSCAPS_VIDEOMEMORY) != 0);
144
145
146 /*
147 ** If this is a hicolor surface, then build the shift values for
148 ** building and extracting the colors from the hicolor pixel.
149 */
150 if (BytesPerPixel == 2) {
151 int index;
152 int shift = Description->ddpfPixelFormat.dwRBitMask;
153 ThisRedRight = 0;
154 ThisRedLeft = 0;
155 for (index = 0; index < 16; index++) {
156 if (shift & 0x01) break;
157 shift >>= 1;
158 ThisRedRight++;
159 }
160 for (index = 0; index < 8; index++) {
161 if (shift & 0x80) break;
162 shift <<= 1;
163 ThisRedLeft++;
164 }
165
166 shift = Description->ddpfPixelFormat.dwGBitMask;
167 ThisGreenRight = 0;
168 ThisGreenLeft = 0;
169 for (index = 0; index < 16; index++) {
170 if (shift & 0x01) break;
172 shift >>= 1;
173 }
174 for (index = 0; index < 8; index++) {
175 if (shift & 0x80) break;
177 shift <<= 1;
178 }
179
180 shift = Description->ddpfPixelFormat.dwBBitMask;
181 ThisBlueRight = 0;
182 ThisBlueLeft = 0;
183 for (index = 0; index < 16; index++) {
184 if (shift & 0x01) break;
186 shift >>= 1;
187 }
188 for (index = 0; index < 8; index++) {
189 if (shift & 0x80) break;
190 ThisBlueLeft++;
191 shift <<= 1;
192 }
193
194 }
195 }
196 }
197}
198
199
200/***********************************************************************************************
201 * DSurface::~DSurface -- Destructor for a direct draw surface object. *
202 * *
203 * This will destruct (make invalid) the direct draw surface. *
204 * *
205 * INPUT: none *
206 * *
207 * OUTPUT: none *
208 * *
209 * WARNINGS: none *
210 * *
211 * HISTORY: *
212 * 02/07/1997 JLB : Created. *
213 *=============================================================================================*/
215{
216 /*
217 ** If this is the primary surface, then the clipper must be detached from
218 ** this surface and the clipper object deleted.
219 */
220 if (IsPrimary && SurfacePtr != NULL && Clipper != NULL) {
221 SurfacePtr->SetClipper(NULL);
222 Clipper->Release();
223 Clipper = NULL;
224 }
225
226 /*
227 ** Delete the description of the surface.
228 */
229 delete Description;
231
232 if (SurfacePtr != NULL) {
233 SurfacePtr->Release();
234 }
236}
237
238
239/***********************************************************************************************
240 * DSurface::DSurface -- Default constructor for surface object. *
241 * *
242 * This default constructor for a surface object should not be used. Although it properly *
243 * creates a non-functional surface, there is no use for such a surface. This default *
244 * constructor is provided for those rare cases where symatics require a default *
245 * constructor. *
246 * *
247 * INPUT: none *
248 * *
249 * OUTPUT: none *
250 * *
251 * WARNINGS: none *
252 * *
253 * HISTORY: *
254 * 02/07/1997 JLB : Created. *
255 *=============================================================================================*/
257 BytesPerPixel(0),
258 LockPtr(NULL),
262{
263 Description = W3DNEW DDSURFACEDESC;
264 memset(Description, '\0', sizeof(DDSURFACEDESC));
265 Description->dwSize = sizeof(DDSURFACEDESC);
266}
267
268
269
270/***********************************************************************************************
271 * DSurface::GetDC -- Get the windows device context from our surface *
272 * *
273 * INPUT: none *
274 * *
275 * OUTPUT: none *
276 * *
277 * WARNINGS: Any current locks will get unlocked while the DC is held *
278 * *
279 * HISTORY: *
280 * 06/21/2000 NAK : Created. *
281 *=============================================================================================*/
283{
284 HDC hdc = NULL;
285 HRESULT hr;
286
287
288 // We have to remove all current locks to get the device context unfortunately...
289 while (LockCount) {
290 Unlock();
292 }
293
294
295 hr = SurfacePtr->GetDC(&hdc);
296 if (hr != DD_OK)
297 {
298 while(DCUnlockCount) // restore the lock state
299 {
300 Lock();
302 }
303 return(NULL);
304 }
305
306 // GetDC() locks the surface internally, so we need to reflect that here
307 if (hr == DD_OK) {
308 LockCount++;
309 }else{
310 hdc = NULL;
311 }
312
313 return (hdc);
314}
315
316
317/***********************************************************************************************
318 * DSurface::ReleaseDC -- Release the windows device context from our surface *
319 * *
320 * INPUT: none *
321 * *
322 * OUTPUT: none *
323 * *
324 * WARNINGS: Restores any locks held before the call to GetDC() *
325 * *
326 * HISTORY: *
327 * 06/21/2000 NAK : Created. *
328 *=============================================================================================*/
330{
331 HRESULT hr;
332
333 hr = SurfacePtr->ReleaseDC(hdc);
334 assert(hr == DD_OK);
335
336 // ReleaseDC() unlocks the surface internally, so we need to reflect that here.
337 if ((hr == DD_OK) && (LockCount > 0)) {
338 LockCount--;
339 }
340
341 while(DCUnlockCount) // restore the lock state
342 {
343 Lock();
345 }
346
347 return (1);
348}
349
350
351
352
353/***********************************************************************************************
354 * DSurface::Create_Primary -- Creates a primary (visible) surface. *
355 * *
356 * This routine is used to create the surface object that represents the currently *
357 * visible display. The surface is not allocated, it is merely linked to the preexisting *
358 * surface that the Windows GDI is also currently using. *
359 * *
360 * INPUT: backsurface -- Optional pointer to specify where the backpage (flip enabled) *
361 * pointer will be placed. If this parameter is NULL, then no *
362 * back surface will be created. *
363 * *
364 * OUTPUT: Returns with a pointer to the primary surface. *
365 * *
366 * WARNINGS: There can be only one primary surface. If an additional call to this routine *
367 * is made, another surface pointer will be returned, but it will point to the *
368 * same surface as before. *
369 * *
370 * HISTORY: *
371 * 02/07/1997 JLB : Created. *
372 *=============================================================================================*/
374{
375 DSurface * surface = W3DNEW DSurface();
376 int backcount = (backsurface1 != NULL) ? 1 : 0;
377
378 /*
379 ** Setup parameter for creating the primary surface. This will
380 ** always be the visible surface plus optional back buffers of identical
381 ** dimensions.
382 */
383 surface->Description->dwFlags = DDSD_CAPS;
384 surface->Description->ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
385 if (backcount > 0) {
386 surface->Description->ddsCaps.dwCaps |= DDSCAPS_FLIP | DDSCAPS_COMPLEX;
387 surface->Description->dwFlags |= DDSD_BACKBUFFERCOUNT;
388 surface->Description->dwBackBufferCount = backcount;
389 }
390 HRESULT result = DirectDrawObject->CreateSurface(surface->Description, &surface->SurfacePtr, NULL);
391
392 /*
393 ** If the primary surface object was created, then fetch a pointer to the
394 ** back buffer if there is one present.
395 */
396 if (result == DD_OK) {
397 if (backcount > 0) {
398 LPDIRECTDRAWSURFACE back;
399 DDSCAPS caps;
400 caps.dwCaps = DDSCAPS_BACKBUFFER;
401 result = surface->SurfacePtr->GetAttachedSurface(&caps, &back);
402 if (result == DD_OK) {
403 *backsurface1 = W3DNEW DSurface(back);
404 }
405 }
406
407 /*
408 ** Get a description of the surface that was just allocated.
409 */
410 memset(surface->Description, '\0', sizeof(DDSURFACEDESC));
411 surface->Description->dwSize = sizeof(DDSURFACEDESC);
412 surface->SurfacePtr->GetSurfaceDesc(surface->Description);
413 surface->BytesPerPixel = (surface->Description->ddpfPixelFormat.dwRGBBitCount+7)/8;
414 surface->IsPrimary = true;
415
416// surface->Window.Set(Rect(0, 0, surface->Description->dwWidth, surface->Description->dwHeight));
417 surface->Width = surface->Description->dwWidth;
418 surface->Height = surface->Description->dwHeight;
419 PaletteSurface = surface->SurfacePtr;
420
421 /*
422 ** Attach a clipper object to the surface so that it can cooperate
423 ** with the system GDI. This only comes into play if there are going
424 ** to be GDI graphical elements on top of the surface (normally this
425 ** isn't the case for full screen games). It doesn't hurt to attach
426 ** a clipper object anyway -- just in case.
427 */
428 if (DirectDrawObject->CreateClipper(0, &Clipper, NULL) == DD_OK) {
429 if (Clipper->SetHWnd(0, GetActiveWindow()) == DD_OK) {
430 surface->SurfacePtr->SetClipper(Clipper);
431 }
432 }
433
434 /*
435 ** Fetch the pixel format for the surface.
436 */
437 memcpy(&PixelFormat, &surface->Description->ddpfPixelFormat, sizeof(DDPIXELFORMAT));
438
439 /*
440 ** If this is a hicolor surface, then build the shift values for
441 ** building and extracting the colors from the hicolor pixel.
442 */
443 if (surface->Bytes_Per_Pixel() == 2) {
444 int index;
445 int shift = PixelFormat.dwRBitMask;
446 RedRight = 0;
447 RedLeft = 0;
448 for (index = 0; index < 16; index++) {
449 if (shift & 0x01) break;
450 shift >>= 1;
451 RedRight++;
452 }
453 for (index = 0; index < 8; index++) {
454 if (shift & 0x80) break;
455 shift <<= 1;
456 RedLeft++;
457 }
458
459 shift = PixelFormat.dwGBitMask;
460 GreenRight = 0;
461 GreenLeft = 0;
462 for (index = 0; index < 16; index++) {
463 if (shift & 0x01) break;
464 GreenRight++;
465 shift >>= 1;
466 }
467 for (index = 0; index < 8; index++) {
468 if (shift & 0x80) break;
469 GreenLeft++;
470 shift <<= 1;
471 }
472
473 shift = PixelFormat.dwBBitMask;
474 BlueRight = 0;
475 BlueLeft = 0;
476 for (index = 0; index < 16; index++) {
477 if (shift & 0x01) break;
478 BlueRight++;
479 shift >>= 1;
480 }
481 for (index = 0; index < 8; index++) {
482 if (shift & 0x80) break;
483 BlueLeft++;
484 shift <<= 1;
485 }
486
487
488 /*
489 ** Create the halfbright mask.
490 */
491 HalfbrightMask = (unsigned short)Build_Hicolor_Pixel(127, 127, 127);
492 QuarterbrightMask = (unsigned short)Build_Hicolor_Pixel(63, 63, 63);
493 EighthbrightMask = (unsigned short)Build_Hicolor_Pixel(31, 31, 31);
494 }
495
496 } else {
497 delete surface;
498 surface = NULL;
499 }
500
501 return(surface);
502}
503
504
505/***********************************************************************************************
506 * DSurface::DSurface -- Create a surface attached to specified DDraw Surface Object. *
507 * *
508 * If an existing Direct Draw Surface Object is available, use this constructor to create *
509 * a DSurface object that is attached to the surface specified. *
510 * *
511 * INPUT: surfaceptr -- Pointer to a preexisting Direct Draw Surface Object. *
512 * *
513 * OUTPUT: none *
514 * *
515 * WARNINGS: none *
516 * *
517 * HISTORY: *
518 * 02/07/1997 JLB : Created. *
519 *=============================================================================================*/
520DSurface::DSurface(LPDIRECTDRAWSURFACE surfaceptr) :
521 BytesPerPixel(0),
522 LockPtr(NULL),
523 SurfacePtr(surfaceptr),
525{
526 if (SurfacePtr != NULL) {
527 Description = W3DNEW DDSURFACEDESC;
528 memset(Description, '\0', sizeof(DDSURFACEDESC));
529 Description->dwSize = sizeof(DDSURFACEDESC);
530 HRESULT result = SurfacePtr->GetSurfaceDesc(Description);
531 if (result == DD_OK) {
532 BytesPerPixel = (Description->ddpfPixelFormat.dwRGBBitCount+7)/8;
533// Window.Set(Rect(0, 0, Description->dwWidth, Description->dwHeight));
534 Width = Description->dwWidth;
535 Height = Description->dwHeight;
536 }
537 }
538}
539
540
541/***********************************************************************************************
542 * DSurface::Bytes_Per_Pixel -- Fetches the bytes per pixel of the surface. *
543 * *
544 * This routine will return with the number of bytes that each pixel consumes. The value *
545 * is dependant upon the graphic mode of the display. *
546 * *
547 * INPUT: none *
548 * *
549 * OUTPUT: Returns with the bytes per pixel of the surface object. *
550 * *
551 * WARNINGS: none *
552 * *
553 * HISTORY: *
554 * 02/07/1997 JLB : Created. *
555 *=============================================================================================*/
557{
558 return(BytesPerPixel);
559}
560
561
562/***********************************************************************************************
563 * DSurface::Stride -- Fetches the bytes between rows. *
564 * *
565 * This routine will return the number of bytes to add so that the pointer will be *
566 * positioned at the same column, but one row down the screen. This value may very well *
567 * NOT be equal to the width multiplied by the bytes per pixel. *
568 * *
569 * INPUT: none *
570 * *
571 * OUTPUT: Returns with the byte difference between subsequent pixel rows. *
572 * *
573 * WARNINGS: none *
574 * *
575 * HISTORY: *
576 * 02/07/1997 JLB : Created. *
577 *=============================================================================================*/
578int DSurface::Stride(void) const
579{
580 return(Description->lPitch);
581}
582
583
584/***********************************************************************************************
585 * DSurface::Lock -- Fetches a working pointer into surface memory. *
586 * *
587 * This routine will return with a pointer to the pixel at the location specified. In order *
588 * to directly manipulate surface memory, the surface memory must be mapped into the *
589 * program's logical address space. In addition, all blitter activity on the surface will *
590 * be suspended. Every call to Lock must be have a corresponding call to Unlock if the *
591 * pointer returned is not equal to NULL. *
592 * *
593 * INPUT: point -- Pixel coordinate to return a pointer to. *
594 * *
595 * OUTPUT: Returns with a pointer to the pixel specified. If the return value is NULL, then *
596 * the surface could not be locked and no call to Unlock should be performed. *
597 * *
598 * WARNINGS: It is important not to keep a surface locked indefinately since the blitter *
599 * will not be able to function. Due to the time that locking consumes, it is *
600 * also important to not perform unnecessarily frequent Lock calls. *
601 * *
602 * HISTORY: *
603 * 02/07/1997 JLB : Created. *
604 *=============================================================================================*/
605void * DSurface::Lock(Point2D point) const
606{
608 if (LockCount == 0) {
609 DDSURFACEDESC desc;
610 memset(&desc, '\0', sizeof(desc));
611 desc.dwSize = sizeof(desc);
612 HRESULT result = SurfacePtr->Lock(NULL, &desc, DDLOCK_SURFACEMEMORYPTR|DDLOCK_WAIT, NULL);
613 if (result != DD_OK) return(NULL);
614 memcpy(Description, &desc, sizeof(DDSURFACEDESC));
615 BytesPerPixel = (Description->ddpfPixelFormat.dwRGBBitCount+7)/8;
616 LockPtr = Description->lpSurface;
617 }
619 return(((char*)LockPtr) + point.Y * Stride() + point.X * Bytes_Per_Pixel());
620}
621
622
623/***********************************************************************************************
624 * DSurface::Unlock -- Unlock a previously locked surface. *
625 * *
626 * After a surface has been successfully locked, a call to the Unlock() function is *
627 * required. *
628 * *
629 * INPUT: none *
630 * *
631 * OUTPUT: bool; Was the unlock successful? *
632 * *
633 * WARNINGS: Only pair a call to Unlock if the prior Lock actually returned a non-NULL *
634 * value. *
635 * *
636 * HISTORY: *
637 * 02/07/1997 JLB : Created. *
638 *=============================================================================================*/
639bool DSurface::Unlock(void) const
640{
642 if (LockCount > 0) {
644 if (LockCount == 0) {
645 SurfacePtr->Unlock(LockPtr);
646 LockPtr = NULL;
647 }
648 return(true);
649 }
650 return(false);
651}
652
653
654/***********************************************************************************************
655 * DSurface::Restore_Check -- Checks for and restores surface memory if necessary. *
656 * *
657 * This routine will check to see if surface memory has been lost to the surface. If it *
658 * has, then the surface memory will be restored. *
659 * *
660 * INPUT: none *
661 * *
662 * OUTPUT: none *
663 * *
664 * WARNINGS: none *
665 * *
666 * HISTORY: *
667 * 02/07/1997 JLB : Created. *
668 *=============================================================================================*/
670{
671 if (SurfacePtr->IsLost() == DDERR_SURFACELOST) {
672 SurfacePtr->Restore();
673 if (LockCount > 0 && SurfacePtr->IsLost() != DDERR_SURFACELOST) {
674 int oldlockcount = LockCount;
675 LockCount = 0;
676 Lock();
677 LockCount++;
678 Unlock();
679 LockCount = oldlockcount;
680 }
681 }
682}
683
684
685/***********************************************************************************************
686 * DSurface::Blit_From -- Blit graphic memory from one rectangle to another. *
687 * *
688 * This routine will use the blitter (if possible) to blit a block of graphic memory from *
689 * one screen rectangle to another. If the rectangles do no match in size, scaling may *
690 * be performed. *
691 * *
692 * INPUT: destrect -- The destination rectangle. *
693 * *
694 * ssource -- The source surface to blit from. *
695 * *
696 * sourecrect -- The source rectangle. *
697 * *
698 * trans -- Should transparency checking be performed? *
699 * *
700 * OUTPUT: bool; Was the blit performed without error? *
701 * *
702 * WARNINGS: none *
703 * *
704 * HISTORY: *
705 * 02/07/1997 JLB : Created. *
706 *=============================================================================================*/
707bool DSurface::Blit_From(Rect const & destrect, Surface const & ssource, Rect const & sourcerect, bool trans)
708{
709 return(Blit_From(Get_Rect(), destrect, ssource, ssource.Get_Rect(), sourcerect, trans));
710}
711
712
713/***********************************************************************************************
714 * DSurface::Blit_From -- Blit from one surface to this one. *
715 * *
716 * Use this routine to blit a rectangle from the specified surface to this surface while *
717 * performing clipping upon the blit rectangles specified. *
718 * *
719 * INPUT: dcliprect -- The clipping rectangle to use for this surface. *
720 * *
721 * destrect -- The destination rectangle of the blit. The is relative to the *
722 * dcliprect parameter. *
723 * *
724 * ssource -- The source surface of the blit. *
725 * *
726 * scliprect -- The source clipping rectangle. *
727 * *
728 * sourcrect -- The source rectangle of the blit. This rectangle is relative to *
729 * the source clipping rectangle. *
730 * *
731 * trans -- Is this a transparent blit request? *
732 * *
733 * OUTPUT: bool; Was there a blit performed? A 'false' return value would indicate that the *
734 * blit was clipped into nothing. *
735 * *
736 * WARNINGS: none *
737 * *
738 * HISTORY: *
739 * 05/27/1997 JLB : Created. *
740 *=============================================================================================*/
741bool DSurface::Blit_From(Rect const & dcliprect, Rect const & destrect, Surface const & ssource, Rect const & scliprect, Rect const & sourcerect, bool trans)
742{
743 if (!dcliprect.Is_Valid() || !scliprect.Is_Valid() || !destrect.Is_Valid() || !sourcerect.Is_Valid()) return(false);
744
745 /*
746 ** For non-direct draw surfaces, perform a manual blit operation. This is also
747 ** necessary if any of the surfaces are currently locked. It is also necessary if the
748 ** blit regions overlap and the blitter cannot handle overlapped regions.
749 **
750 ** NOTE: Its legal to blit to a locked surface but not from a locked surface.
751 ** ST - 4/23/97 1:03AM
752 */
753 if (!ssource.Is_Direct_Draw() || ((DSurface&)ssource).Is_Locked() || trans || Bytes_Per_Pixel() != ssource.Bytes_Per_Pixel()) {
754 return(XSurface::Blit_From(destrect, ssource, sourcerect, trans));
755 }
756
758 DSurface const & source = (DSurface const &)ssource;
759
760 Rect drect = destrect;
761 Rect srect = sourcerect;
762 Rect swindow = scliprect.Intersect(ssource.Get_Rect());
763 Rect dwindow = dcliprect.Intersect(Get_Rect());
764 if (Blit_Clip(drect, dwindow, srect, swindow)) {
765 RECT xdestrect;
766 xdestrect.left = drect.X+dwindow.X;
767 xdestrect.top = drect.Y+dwindow.Y;
768 xdestrect.right = drect.X+dwindow.X+drect.Width;
769 xdestrect.bottom = drect.Y+dwindow.Y+drect.Height;
770
771 RECT xsrcrect;
772 xsrcrect.left = srect.X+swindow.X;
773 xsrcrect.top = srect.Y+swindow.Y;
774 xsrcrect.right = srect.X+swindow.X+srect.Width;
775 xsrcrect.bottom = srect.Y+swindow.Y+srect.Height;
776
777 HRESULT result = SurfacePtr->Blt(&xdestrect, source.SurfacePtr, &xsrcrect, DDBLT_WAIT, NULL);
778 return(result == DD_OK);
779 }
780 return(false);
781}
782
783
784/***********************************************************************************************
785 * DSurface::Fill_Rect -- This routine will fill the specified rectangle. *
786 * *
787 * This routine will fill the specified rectangle with a color. *
788 * *
789 * INPUT: fillrect -- The rectangle to fill. *
790 * *
791 * color -- The color to fill with. *
792 * *
793 * OUTPUT: bool; Was the fill performed without error? *
794 * *
795 * WARNINGS: none *
796 * *
797 * HISTORY: *
798 * 02/07/1997 JLB : Created. *
799 *=============================================================================================*/
800bool DSurface::Fill_Rect(Rect const & fillrect, int color)
801{
802 return(DSurface::Fill_Rect(Get_Rect(), fillrect, color));
803}
804
805
806/***********************************************************************************************
807 * DSurface::Fill_Rect -- Fills a rectangle with clipping control. *
808 * *
809 * This routine will fill a rectangle on this surface, but will clip the request against *
810 * a clipping rectangle first. *
811 * *
812 * INPUT: cliprect -- The clipping rectangle to use for this surface. *
813 * *
814 * fillrect -- The rectangle to fill with the specified color. The rectangle is *
815 * relative to the clipping rectangle. *
816 * *
817 * color -- The color (surface dependant format) to use when filling the rectangle *
818 * pixels. *
819 * *
820 * OUTPUT: bool; Was a fill operation performed? A 'false' return value would mean that the *
821 * fill request was clipped into nothing. *
822 * *
823 * WARNINGS: none *
824 * *
825 * HISTORY: *
826 * 05/27/1997 JLB : Created. *
827 *=============================================================================================*/
828bool DSurface::Fill_Rect(Rect const & cliprect, Rect const & fillrect, int color)
829{
830 if (!fillrect.Is_Valid()) return(false);
831
832 /*
833 ** If the buffer is locked, then using the blitter to perform the fill is not possible.
834 ** In such a case, perform a manual fill of the region.
835 */
836 if (Is_Locked()) {
837 return(XSurface::Fill_Rect(cliprect, fillrect, color));
838 }
839
841
842 /*
843 ** Ensure that the clipping rectangle is legal.
844 */
845 Rect crect = cliprect.Intersect(Get_Rect());
846
847 /*
848 ** Bias the fill rect to the clipping rectangle.
849 */
850 Rect frect = fillrect.Bias_To(cliprect);
851
852 /*
853 ** Find the region that should be filled after being clipped by the
854 ** clipping rectangle. This could result in no fill operation being performed
855 ** if the desired fill rectangle has been completely clipped away.
856 */
857 frect = frect.Intersect(crect);
858 if (!frect.Is_Valid()) return(false);
859
860 RECT rect;
861 rect.left = frect.X;
862 rect.top = frect.Y;
863 rect.right = rect.left + frect.Width;
864 rect.bottom = rect.top + frect.Height;
865
866 DDBLTFX fx;
867 memset(&fx, '\0', sizeof(fx));
868 fx.dwSize = sizeof(fx);
869 fx.dwFillColor = color;
870 HRESULT result = SurfacePtr->Blt(&rect, NULL, NULL, DDBLT_WAIT|DDBLT_COLORFILL, &fx);
871 return(result == DD_OK);
872}
873
874
875/***********************************************************************************************
876 * DSurface::Build_Hicolor_Pixel -- Construct a hicolor pixel according to the surface pixel f *
877 * *
878 * This routine will construct a pixel according to the highcolor pixel format for this *
879 * surface. *
880 * *
881 * INPUT: red -- The red component of the color (0..255). *
882 * *
883 * green -- The green component of the color (0..255). *
884 * *
885 * blue -- The blue component of the color (0..255). *
886 * *
887 * OUTPUT: Returns with a screen format pixel number that most closesly matches the color *
888 * specified. *
889 * *
890 * WARNINGS: The return value is card dependant and only applies to hicolor displays. *
891 * *
892 * HISTORY: *
893 * 05/27/1997 JLB : Created. *
894 *=============================================================================================*/
895int DSurface::Build_Hicolor_Pixel(int red, int green, int blue)
896{
897 return(((red >> RedLeft) << RedRight) | ((green >> GreenLeft) << GreenRight) | ((blue >> BlueLeft) << BlueRight));
898}
899
900
901/***********************************************************************************************
902 * DSurface::Build_Remap_Table -- Build a highcolor remap table. *
903 * *
904 * This will build a complete hicolor remap table for the palette specified. This table *
905 * can then be used to quickly fetch a pixel that matches the color index of the palette. *
906 * *
907 * INPUT: table -- The location to store the hicolor table. The buffer must be 256*2 bytes *
908 * long. *
909 * *
910 * palette -- The palette to use to create the remap table. *
911 * *
912 * OUTPUT: none *
913 * *
914 * WARNINGS: none *
915 * *
916 * HISTORY: *
917 * 05/27/1997 JLB : Created. *
918 *=============================================================================================*/
919void DSurface::Build_Remap_Table(unsigned short * table, PaletteClass const & palette)
920{
921 assert(table != NULL);
922
923 /*
924 ** Build the hicolor index table according to the palette.
925 */
926 for (int index = 0; index < 256; index++) {
927 table[index] = (unsigned short)Build_Hicolor_Pixel(palette[index].Get_Red(), palette[index].Get_Green(), palette[index].Get_Blue());
928 }
929}
930
931
#define NULL
Definition BaseType.h:92
UnicodeString shift
#define W3DNEW
Definition always.h:109
@ false
Definition bool.h:59
static int BlueLeft
Definition dsurface.h:170
int BytesPerPixel
Definition dsurface.h:126
int ThisGreenLeft
Definition dsurface.h:183
static LPDIRECTDRAWCLIPPER Clipper
Definition dsurface.h:156
static int RedRight
Definition dsurface.h:167
static unsigned short QuarterbrightMask
Definition dsurface.h:187
LPDIRECTDRAWSURFACE SurfacePtr
Definition dsurface.h:149
virtual int Stride(void) const
Definition dsurface.cpp:578
int ThisRedLeft
Definition dsurface.h:179
static int Build_Hicolor_Pixel(int red, int green, int blue)
Definition dsurface.cpp:895
virtual bool Fill_Rect(Rect const &rect, int color)
Definition dsurface.cpp:800
static int RedLeft
Definition dsurface.h:168
HDC GetDC(void)
Definition dsurface.cpp:282
void Restore_Check(void) const
Definition dsurface.cpp:669
int ThisRedRight
Definition dsurface.h:178
static unsigned short EighthbrightMask
Definition dsurface.h:188
virtual bool Blit_From(Rect const &dcliprect, Rect const &destrect, Surface const &source, Rect const &scliprect, Rect const &sourcerect, bool trans=false)
Definition dsurface.cpp:741
int ThisBlueLeft
Definition dsurface.h:181
static unsigned short HalfbrightMask
Definition dsurface.h:186
static void Build_Remap_Table(unsigned short *table, PaletteClass const &palette)
Definition dsurface.cpp:919
virtual ~DSurface(void)
Definition dsurface.cpp:214
int ThisBlueRight
Definition dsurface.h:180
static DSurface * Create_Primary(DSurface **backsurface1=NULL)
Definition dsurface.cpp:373
virtual void * Lock(Point2D point=Point2D(0, 0)) const
Definition dsurface.cpp:605
static int GreenLeft
Definition dsurface.h:172
int DCUnlockCount
Definition dsurface.h:194
static int BlueRight
Definition dsurface.h:169
static DDPIXELFORMAT PixelFormat
Definition dsurface.h:161
bool IsPrimary
Definition dsurface.h:139
static int GreenRight
Definition dsurface.h:171
virtual int Bytes_Per_Pixel(void) const
Definition dsurface.cpp:556
int ReleaseDC(HDC hdc)
Definition dsurface.cpp:329
void * LockPtr
Definition dsurface.h:133
bool IsVideoRam
Definition dsurface.h:144
DSurface(void)
Definition dsurface.cpp:256
int ThisGreenRight
Definition dsurface.h:182
virtual bool Unlock(void) const
Definition dsurface.cpp:639
DDSURFACEDESC * Description
Definition dsurface.h:150
virtual Rect Get_Rect(void) const
Definition Surface.h:102
int Height
Definition Surface.h:119
virtual int Bytes_Per_Pixel(void) const =0
Surface(int width, int height)
Definition Surface.h:55
virtual bool Is_Direct_Draw(void) const
Definition Surface.h:111
int Width
Definition Surface.h:118
TRect< T > const Bias_To(TRect< T > const &rect) const
Definition trect.h:72
bool Is_Valid(void) const
Definition trect.h:82
T Width
Definition trect.h:115
T Y
Definition trect.h:109
T Height
Definition trect.h:116
TRect< T > const Intersect(TRect< T > const &rectangle, T *x=NULL, T *y=NULL) const
Definition trect.h:121
T X
Definition trect.h:108
XSurface(int width=0, int height=0)
Definition xsurface.h:54
virtual bool Is_Locked(void) const
Definition xsurface.h:94
virtual bool Unlock(void) const
Definition xsurface.h:93
virtual bool Blit_From(Rect const &dcliprect, Rect const &destrect, Surface const &source, Rect const &scliprect, Rect const &sourcerect, bool trans=false)
Definition xsurface.cpp:525
virtual void * Lock(Point2D=Point2D(0, 0)) const
Definition xsurface.h:92
int LockCount
Definition xsurface.h:126
virtual bool Fill_Rect(Rect const &rect, int color)
Definition xsurface.cpp:355
LPDIRECTDRAW DirectDrawObject
Definition ddraw.cpp:55
LPDIRECTDRAWSURFACE PaletteSurface
Definition ddraw.cpp:61
TRect< int > Rect
Definition trect.h:221
bool Blit_Clip(Rect &drect, Rect const &dwindow, Rect &srect, Rect const &swindow)
Definition xsurface.cpp:576