GBUFFER.CPP (32817B)
1 // 2 // Copyright 2020 Electronic Arts Inc. 3 // 4 // TiberianDawn.DLL and RedAlert.dll and corresponding source code is free 5 // software: you can redistribute it and/or modify it under the terms of 6 // the GNU General Public License as published by the Free Software Foundation, 7 // either version 3 of the License, or (at your option) any later version. 8 9 // TiberianDawn.DLL and RedAlert.dll and corresponding source code is distributed 10 // in the hope that it will be useful, but with permitted additional restrictions 11 // under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT 12 // distributed with this program. You should have received a copy of the 13 // GNU General Public License along with permitted additional restrictions 14 // with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection 15 16 /*************************************************************************** 17 ** C O N F I D E N T I A L --- W E S T W O O D A S S O C I A T E S ** 18 *************************************************************************** 19 * * 20 * Project Name : Westwood 32 bit Library * 21 * * 22 * File Name : GBUFFER.CPP * 23 * * 24 * Programmer : Phil W. Gorrow * 25 * * 26 * Start Date : May 3, 1994 * 27 * * 28 * Last Update : October 9, 1995 [] * 29 * * 30 *-------------------------------------------------------------------------* 31 * Functions: * 32 * VVPC::VirtualViewPort -- Default constructor for a virtual viewport * 33 * VVPC:~VirtualViewPortClass -- Destructor for a virtual viewport * 34 * VVPC::Clear -- Clears a graphic page to correct color * 35 * VBC::VideoBufferClass -- Lowlevel constructor for video buffer class * 36 * GVPC::Change -- Changes position and size of a Graphic View Port * 37 * VVPC::Change -- Changes position and size of a Video View Port * 38 * Set_Logic_Page -- Sets LogicPage to new buffer * 39 * GBC::DD_Init -- Inits a direct draw surface for a GBC * 40 * GBC::Init -- Core function responsible for initing a GBC * 41 * GBC::Lock -- Locks a Direct Draw Surface * 42 * GBC::Unlock -- Unlocks a direct draw surface * 43 * GBC::GraphicBufferClass -- Default constructor (requires explicit init)* 44 * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ 45 46 #ifndef GBUFFER_H 47 #include "gbuffer.h" 48 #include "misc.h" 49 #endif 50 //#pragma inline 51 52 int TotalLocks; 53 BOOL AllowHardwareBlitFills = TRUE; 54 55 56 //int CacheAllowed; 57 58 /*=========================================================================*/ 59 /* The following PRIVATE functions are in this file: */ 60 /*=========================================================================*/ 61 62 63 /*= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =*/ 64 65 66 67 /*************************************************************************** 68 * GVPC::GRAPHICVIEWPORTCLASS -- Constructor for basic view port class * 69 * m * 70 * INPUT: GraphicBufferClass * gbuffer - buffer to attach to * 71 * int x - x offset into buffer * 72 * int y - y offset into buffer * 73 * int w - view port width in pixels * 74 * int h - view port height in pixels * 75 * * 76 * OUTPUT: Constructors may not have a return value * 77 * * 78 * HISTORY: * 79 * 05/09/1994 PWG : Created. * 80 *=========================================================================*/ 81 GraphicViewPortClass::GraphicViewPortClass(GraphicBufferClass *gbuffer, int x, int y, int w, int h) : 82 LockCount(0), 83 GraphicBuff(NULL) 84 { 85 Attach(gbuffer, x, y, w, h); 86 } 87 88 /*************************************************************************** 89 * GVPC::GRAPHICVIEWPORTCLASS -- Default constructor for view port class * 90 * * 91 * INPUT: none * 92 * * 93 * OUTPUT: none * 94 * * 95 * HISTORY: * 96 * 05/09/1994 PWG : Created. * 97 *=========================================================================*/ 98 GraphicViewPortClass::GraphicViewPortClass(void) 99 { 100 } 101 102 /*************************************************************************** 103 * GVPC::~GRAPHICVIEWPORTCLASS -- Destructor for GraphicViewPortClass * 104 * * 105 * INPUT: none * 106 * * 107 * OUTPUT: A destructor may not return a value. * 108 * * 109 * HISTORY: * 110 * 05/10/1994 PWG : Created. * 111 *=========================================================================*/ 112 GraphicViewPortClass::~GraphicViewPortClass(void) 113 { 114 Offset = 0; 115 Width = 0; // Record width of Buffer 116 Height = 0; // Record height of Buffer 117 XAdd = 0; // Record XAdd of Buffer 118 XPos = 0; // Record XPos of Buffer 119 YPos = 0; // Record YPos of Buffer 120 Pitch = 0; // Record width of Buffer 121 IsDirectDraw = FALSE; 122 LockCount = 0; 123 GraphicBuff = NULL; 124 } 125 126 /*************************************************************************** 127 * GVPC::ATTACH -- Attaches a viewport to a buffer class * 128 * * 129 * INPUT: GraphicBufferClass *g_buff - pointer to gbuff to attach to * 130 * int x - x position to attach to * 131 * int y - y position to attach to * 132 * int w - width of the view port * 133 * int h - height of the view port * 134 * * 135 * OUTPUT: none * 136 * * 137 * HISTORY: * 138 * 05/10/1994 PWG : Created. * 139 *=========================================================================*/ 140 void GraphicViewPortClass::Attach(GraphicBufferClass *gbuffer, int x, int y, int w, int h) 141 { 142 /*======================================================================*/ 143 /* Can not attach a Graphic View Port if it is actually the physical */ 144 /* representation of a Graphic Buffer. */ 145 /*======================================================================*/ 146 if (this == Get_Graphic_Buffer()) { 147 return; 148 } 149 150 /*======================================================================*/ 151 /* Verify that the x and y coordinates are valid and placed within the */ 152 /* physical buffer. */ 153 /*======================================================================*/ 154 if (x < 0) // you cannot place view port off 155 x = 0; // the left edge of physical buf 156 if (x >= gbuffer->Get_Width()) // you cannot place left edge off 157 x = gbuffer->Get_Width() - 1; // the right edge of physical buf 158 if (y < 0) // you cannot place view port off 159 y = 0; // the top edge of physical buf 160 if (y >= gbuffer->Get_Height()) // you cannot place view port off 161 y = gbuffer->Get_Height() - 1; // bottom edge of physical buf 162 163 /*======================================================================*/ 164 /* Adjust the width and height of necessary */ 165 /*======================================================================*/ 166 if (x + w > gbuffer->Get_Width()) // if the x plus width is larger 167 w = gbuffer->Get_Width() - x; // than physical, fix width 168 169 if (y + h > gbuffer->Get_Height()) // if the y plus height is larger 170 h = gbuffer->Get_Height() - y; // than physical, fix height 171 172 /*======================================================================*/ 173 /* Get a pointer to the top left edge of the buffer. */ 174 /*======================================================================*/ 175 Offset = gbuffer->Get_Offset() + ((gbuffer->Get_Width()+gbuffer->Get_Pitch()) * y) + x; 176 177 /*======================================================================*/ 178 /* Copy over all of the variables that we need to store. */ 179 /*======================================================================*/ 180 XPos = x; 181 YPos = y; 182 XAdd = gbuffer->Get_Width() - w; 183 Width = w; 184 Height = h; 185 Pitch = gbuffer->Get_Pitch(); 186 GraphicBuff = gbuffer; 187 IsDirectDraw= gbuffer->IsDirectDraw; 188 } 189 190 191 /*************************************************************************** 192 * GVPC::CHANGE -- Changes position and size of a Graphic View Port * 193 * * 194 * INPUT: int the new x pixel position of the graphic view port * 195 * int the new y pixel position of the graphic view port * 196 * int the new width of the viewport in pixels * 197 * int the new height of the viewport in pixels * 198 * * 199 * OUTPUT: BOOL whether the Graphic View Port could be sucessfully * 200 * resized. * 201 * * 202 * WARNINGS: You may not resize a Graphic View Port which is derived * 203 * from a Graphic View Port Buffer, * 204 * * 205 * HISTORY: * 206 * 09/14/1994 SKB : Created. * 207 *=========================================================================*/ 208 BOOL GraphicViewPortClass::Change(int x, int y, int w, int h) 209 { 210 /*======================================================================*/ 211 /* Can not change a Graphic View Port if it is actually the physical */ 212 /* representation of a Graphic Buffer. */ 213 /*======================================================================*/ 214 if (this == Get_Graphic_Buffer()) { 215 return(FALSE); 216 } 217 218 /*======================================================================*/ 219 /* Since there is no allocated information, just re-attach it to the */ 220 /* existing graphic buffer as if we were creating the */ 221 /* GraphicViewPort. */ 222 /*======================================================================*/ 223 Attach(Get_Graphic_Buffer(), x, y, w, h); 224 return(TRUE); 225 } 226 227 228 /*************************************************************************** 229 * GBC::DD_INIT -- Inits a direct draw surface for a GBC * 230 * * 231 * INPUT: none * 232 * * 233 * OUTPUT: none * 234 * * 235 * HISTORY: * 236 * 10/09/1995 : Created. * 237 *=========================================================================*/ 238 void GraphicBufferClass::DD_Init(GBC_Enum flags) 239 { 240 // 241 // Create the direct draw surface description 242 // 243 memset (&VideoSurfaceDescription , 0 , sizeof ( VideoSurfaceDescription )); 244 245 VideoSurfaceDescription.dwSize = sizeof( VideoSurfaceDescription ); 246 VideoSurfaceDescription.dwFlags = DDSD_CAPS; 247 VideoSurfaceDescription.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE; 248 249 250 if (!(flags & GBC_VISIBLE)) { 251 VideoSurfaceDescription.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN; 252 VideoSurfaceDescription.dwFlags |= DDSD_HEIGHT | DDSD_WIDTH; 253 VideoSurfaceDescription.dwHeight = Height; 254 VideoSurfaceDescription.dwWidth = Width; 255 } 256 257 // 258 // Need to set the DDSCAPS_MODEX flag if we want a 320 wide mode 259 // 260 if ( Width == 320 ) { 261 VideoSurfaceDescription.ddsCaps.dwCaps |= DDSCAPS_MODEX; 262 } 263 264 // 265 // Call CreateSurface 266 // 267 DirectDrawObject->CreateSurface( &VideoSurfaceDescription , &VideoSurfacePtr , NULL); 268 AllSurfaces.Add_DD_Surface (VideoSurfacePtr); 269 270 if ( GBC_VISIBLE & flags ){ 271 PaletteSurface=VideoSurfacePtr; 272 } 273 274 Allocated = FALSE; // even if system alloced, dont flag it cuz 275 // we dont want it freed. 276 IsDirectDraw = TRUE; // flag it as a video surface 277 Offset = NOT_LOCKED; // flag it as unavailable for reading or writing 278 LockCount = 0; // surface is not locked 279 } 280 281 282 void GraphicBufferClass::Attach_DD_Surface (GraphicBufferClass * attach_buffer) 283 { 284 VideoSurfacePtr->AddAttachedSurface (attach_buffer->Get_DD_Surface()); 285 } 286 287 288 /*************************************************************************** 289 * GBC::INIT -- Core function responsible for initing a GBC * 290 * * 291 * INPUT: int - the width in pixels of the GraphicBufferClass * 292 * int - the heigh in pixels of the GraphicBufferClass * 293 * void * - pointer to user supplied buffer (system will * 294 * allocate space if buffer is NULL) * 295 * long - size of the user provided buffer * 296 * GBC_Enum - flags if this is defined as a direct draw * 297 * surface * 298 * * 299 * OUTPUT: none * 300 * * 301 * HISTORY: * 302 * 10/09/1995 : Created. * 303 *=========================================================================*/ 304 void GraphicBufferClass::Init(int w, int h, void *buffer, long size, GBC_Enum flags) 305 { 306 Size = size; // find size of physical buffer 307 Width = w; // Record width of Buffer 308 Height = h; // Record height of Buffer 309 310 // 311 // If the surface we are creating is a direct draw object then 312 // we need to do a direct draw init. Otherwise we will do 313 // a normal alloc. 314 // 315 if (flags & (GBC_VIDEOMEM | GBC_VISIBLE)) { 316 DD_Init(flags); 317 } else { 318 if (buffer) { // if buffer is specified 319 Buffer = (BYTE *)buffer; // point to it and mark 320 Allocated = FALSE; // it as user allocated 321 } else { 322 if (!Size) Size = w*h; 323 Buffer = new BYTE[Size]; // otherwise allocate it and 324 Allocated = TRUE; // mark it system alloced 325 } 326 Offset = (long)Buffer; // Get offset to the buffer 327 IsDirectDraw = FALSE; 328 } 329 330 Pitch = 0; // Record width of Buffer 331 XAdd = 0; // Record XAdd of Buffer 332 XPos = 0; // Record XPos of Buffer 333 YPos = 0; // Record YPos of Buffer 334 GraphicBuff = this; // Get a pointer to our self 335 } 336 337 338 /*********************************************************************************************** 339 * GBC::Un_Init -- releases the video surface belonging to this gbuffer * 340 * * 341 * * 342 * * 343 * INPUT: Nothing * 344 * * 345 * OUTPUT: Nothing * 346 * * 347 * WARNINGS: None * 348 * * 349 * HISTORY: * 350 * 6/6/96 12:44PM ST : Created * 351 *=============================================================================================*/ 352 353 void GraphicBufferClass::Un_Init (void) 354 { 355 if ( IsDirectDraw ){ 356 357 if ( VideoSurfacePtr ){ 358 359 while ( LockCount ){ 360 361 if (VideoSurfacePtr->Unlock ( NULL ) == DDERR_SURFACELOST){ 362 if (Gbuffer_Focus_Loss_Function){ 363 Gbuffer_Focus_Loss_Function(); 364 } 365 AllSurfaces.Restore_Surfaces(); 366 } 367 } 368 369 AllSurfaces.Remove_DD_Surface (VideoSurfacePtr); 370 VideoSurfacePtr->Release(); 371 VideoSurfacePtr = NULL; 372 } 373 } 374 } 375 376 377 /*************************************************************************** 378 * GBC::GRAPHICBUFFERCLASS -- Default constructor (requires explicit init) * 379 * * 380 * INPUT: none * 381 * * 382 * OUTPUT: none * 383 * * 384 * HISTORY: * 385 * 10/09/1995 : Created. * 386 *=========================================================================*/ 387 GraphicBufferClass::GraphicBufferClass(void) 388 { 389 GraphicBuff = this; // Get a pointer to our self 390 VideoSurfacePtr = NULL; 391 memset(&VideoSurfaceDescription, 0, sizeof(DDSURFACEDESC)); 392 } 393 394 395 /*************************************************************************** 396 * GBC::GRAPHICBUFFERCLASS -- Constructor for fixed size buffers * 397 * * 398 * INPUT: long size - size of the buffer to create * 399 * int w - width of buffer in pixels (default = 320) * 400 * int h - height of buffer in pixels (default = 200) * 401 * void *buffer - a pointer to the buffer if any (optional) * 402 * * 403 * OUTPUT: * 404 * * 405 * WARNINGS: * 406 * * 407 * HISTORY: * 408 * 05/13/1994 PWG : Created. * 409 *=========================================================================*/ 410 GraphicBufferClass::GraphicBufferClass(int w, int h, void *buffer, long size) 411 { 412 Init(w, h, buffer, size, GBC_NONE); 413 } 414 /*=========================================================================* 415 * GBC::GRAPHICBUFFERCLASS -- inline constructor for GraphicBufferClass * 416 * * 417 * INPUT: int w - width of buffer in pixels (default = 320) * 418 * int h - height of buffer in pixels (default = 200) * 419 * void *buffer - a pointer to the buffer if any (optional) * 420 * * 421 * OUTPUT: none * 422 * * 423 * HISTORY: * 424 * 05/03/1994 PWG : Created. * 425 *=========================================================================*/ 426 GraphicBufferClass::GraphicBufferClass(int w, int h, void *buffer) 427 { 428 Init(w, h, buffer, w * h, GBC_NONE); 429 } 430 431 /*====================================================================================* 432 * GBC::GRAPHICBUFFERCLASS -- contructor for GraphicsBufferClass with special flags * 433 * * 434 * INPUT: int w - width of buffer in pixels (default = 320) * 435 * int h - height of buffer in pixels (default = 200) * 436 * void *buffer - unused * 437 * unsigned flags - flags for creation of special buffer types * 438 * GBC_VISIBLE - buffer is a visible screen surface * 439 * GBC_VIDEOMEM - buffer resides in video memory * 440 * * 441 * OUTPUT: none * 442 * * 443 * HISTORY: * 444 * 09-21-95 04:19pm ST : Created * 445 *====================================================================================*/ 446 GraphicBufferClass::GraphicBufferClass(int w, int h, GBC_Enum flags) 447 { 448 Init(w, h, NULL, w * h, flags); 449 } 450 451 /*=========================================================================* 452 * GBC::~GRAPHICBUFFERCLASS -- Destructor for the graphic buffer class * 453 * * 454 * INPUT: none * 455 * * 456 * OUTPUT: none * 457 * * 458 * HISTORY: * 459 * 05/03/1994 PWG : Created. * 460 *=========================================================================*/ 461 GraphicBufferClass::~GraphicBufferClass() 462 { 463 464 // 465 // Release the direct draw surface if it exists 466 // 467 Un_Init(); 468 } 469 470 471 472 /*************************************************************************** 473 * SET_LOGIC_PAGE -- Sets LogicPage to new buffer * 474 * * 475 * INPUT: GraphicBufferClass * the buffer we are going to set * 476 * * 477 * OUTPUT: GraphicBufferClass * the previous buffer type * 478 * * 479 * WARNINGS: * 480 * * 481 * HISTORY: * 482 * 02/23/1995 PWG : Created. * 483 *=========================================================================*/ 484 GraphicViewPortClass *Set_Logic_Page(GraphicViewPortClass *ptr) 485 { 486 GraphicViewPortClass *old = LogicPage; 487 LogicPage = ptr; 488 return(old); 489 } 490 491 /*************************************************************************** 492 * SET_LOGIC_PAGE -- Sets LogicPage to new buffer * 493 * * 494 * INPUT: GraphicBufferClass & the buffer we are going to set * 495 * * 496 * OUTPUT: GraphicBufferClass * the previous buffer type * 497 * * 498 * WARNINGS: * 499 * * 500 * HISTORY: * 501 * 02/23/1995 PWG : Created. * 502 *=========================================================================*/ 503 GraphicViewPortClass *Set_Logic_Page(GraphicViewPortClass &ptr) 504 { 505 GraphicViewPortClass *old = LogicPage; 506 LogicPage = &ptr; 507 return(old); 508 } 509 510 511 /*************************************************************************** 512 * GBC::LOCK -- Locks a Direct Draw Surface * 513 * * 514 * INPUT: none * 515 * * 516 * OUTPUT: none * 517 * * 518 * HISTORY: * 519 * 10/09/1995 : Created. * 520 * 10/09/1995 : Code stolen from Steve Tall * 521 *=========================================================================*/ 522 extern void Colour_Debug (int call_number); 523 extern bool GameInFocus; 524 525 extern void Block_Mouse(GraphicBufferClass *buffer); 526 extern void Unblock_Mouse(GraphicBufferClass *buffer); 527 528 BOOL GraphicBufferClass::Lock(void) 529 { 530 HRESULT result; 531 int restore_attempts=0; 532 533 // 534 // If its not a direct draw surface then the lock is always sucessful. 535 // 536 if (!IsDirectDraw) return(TRUE); 537 538 /* 539 ** If the video surface pointer is null then return 540 */ 541 if (!VideoSurfacePtr) return (FALSE); 542 543 /* 544 ** If we dont have focus then return failure 545 */ 546 if (!GameInFocus) return (FALSE); 547 548 549 Block_Mouse(this); 550 551 552 // 553 // If surface is already locked then inc the lock count and return true 554 // 555 if (LockCount){ 556 LockCount++; 557 Unblock_Mouse(this); 558 return(TRUE); 559 } 560 561 // 562 // If it isn't locked at all then we will have to request that Direct 563 // Draw actually lock the surface. 564 // 565 566 if (VideoSurfacePtr){ 567 while (!LockCount && restore_attempts<2) { 568 result = VideoSurfacePtr->Lock ( NULL 569 , &(VideoSurfaceDescription) 570 , DDLOCK_WAIT 571 , NULL); 572 573 switch (result){ 574 case DD_OK : 575 Offset = (unsigned long)VideoSurfaceDescription.lpSurface; 576 Pitch = VideoSurfaceDescription.lPitch; 577 Pitch -= Width; 578 LockCount++; // increment count so we can track if 579 TotalLocks++; // Total number of times we have locked (for debugging) 580 //Colour_Debug (1); 581 Unblock_Mouse(this); 582 return (TRUE); // we locked it multiple times. 583 584 case DDERR_SURFACELOST : 585 if (Gbuffer_Focus_Loss_Function){ 586 Gbuffer_Focus_Loss_Function(); 587 } 588 AllSurfaces.Restore_Surfaces(); 589 restore_attempts++; 590 break; 591 592 default : 593 Unblock_Mouse(this); 594 return (FALSE); 595 } 596 } 597 } 598 //Colour_Debug(1); 599 Unblock_Mouse(this); 600 return (FALSE); //Return false because we couldnt lock or restore the surface 601 } 602 603 /*************************************************************************** 604 * GBC::UNLOCK -- Unlocks a direct draw surface * 605 * * 606 * INPUT: none * 607 * * 608 * OUTPUT: none * 609 * * 610 * HISTORY: * 611 * 10/09/1995 : Created. * 612 * 10/09/1995 : Code stolen from Steve Tall * 613 *=========================================================================*/ 614 615 616 BOOL GraphicBufferClass::Unlock(void) 617 { 618 // 619 // If there is no lock count or this is not a direct draw surface 620 // then just return true as there is no harm done. 621 // 622 if (!(LockCount && IsDirectDraw)) { 623 return(TRUE); 624 } 625 626 // 627 // If lock count is directly equal to one then we actually need to 628 // unlock so just give it a shot. 629 // 630 if (LockCount == 1 && VideoSurfacePtr) { 631 Block_Mouse(this); 632 if ( VideoSurfacePtr->Unlock ( NULL ) != DD_OK ){ 633 Unblock_Mouse(this); 634 return(FALSE); 635 } else { 636 Offset=NOT_LOCKED; 637 LockCount--; 638 Unblock_Mouse(this); 639 return(TRUE); 640 } 641 } 642 //Colour_Debug (0); 643 LockCount--; 644 return(TRUE); 645 } 646 647 648 /*********************************************************************************************** 649 * GVPC::DD_Linear_Blit_To_Linear -- blit using the hardware blitter * 650 * * 651 * * 652 * * 653 * INPUT: destination vvpc * 654 * x coord to blit from * 655 * y coord to blit from * 656 * x coord to blit to * 657 * y coord to blit to * 658 * width to blit * 659 * height to blit * 660 * * 661 * OUTPUT: DD_OK if successful * 662 * * 663 * WARNINGS: None * 664 * * 665 * HISTORY: * 666 * 09-22-95 11:05am ST : Created * 667 *=============================================================================================*/ 668 669 HRESULT GraphicViewPortClass::DD_Linear_Blit_To_Linear ( 670 GraphicViewPortClass &dest 671 , int source_x 672 , int source_y 673 , int dest_x 674 , int dest_y 675 , int width 676 , int height 677 , BOOL mask ) 678 679 { 680 RECT source_rectangle; 681 RECT dest_rectangle; 682 int key_source=0; 683 684 if ( mask ){ 685 key_source=DDBLT_KEYSRC; 686 } 687 688 689 source_rectangle.left = source_x; 690 source_rectangle.top = source_y; 691 source_rectangle.right = source_x+width; 692 source_rectangle.bottom = source_y+height; 693 694 dest_rectangle.left = dest_x; 695 dest_rectangle.top = dest_y; 696 dest_rectangle.right = dest_x+width; 697 dest_rectangle.bottom = dest_y+height; 698 699 return ( dest.GraphicBuff->Get_DD_Surface()->Blt ( &dest_rectangle, 700 GraphicBuff->Get_DD_Surface(), 701 &source_rectangle, 702 key_source | DDBLT_WAIT | DDBLT_ASYNC, 703 NULL ) ); 704 } 705 706 707