Home | Info | Community | Development | myReactOS | Contact Us
ReactOS Development > Doxygenstretchblt.c
Go to the documentation of this file.
00001 /* 00002 * COPYRIGHT: See COPYING in the top level directory 00003 * PROJECT: ReactOS Win32k subsystem 00004 * PURPOSE: GDI stretch blt functions 00005 * FILE: subsystems/win32/win32k/eng/stretchblt.c 00006 * PROGRAMER: Jason Filby 00007 */ 00008 00009 #include <win32k.h> 00010 00011 #define NDEBUG 00012 #include <debug.h> 00013 00014 typedef BOOLEAN (APIENTRY *PSTRETCHRECTFUNC)(SURFOBJ* OutputObj, 00015 SURFOBJ* InputObj, 00016 SURFOBJ* Mask, 00017 XLATEOBJ* ColorTranslation, 00018 RECTL* OutputRect, 00019 RECTL* InputRect, 00020 POINTL* MaskOrigin, 00021 BRUSHOBJ* pbo, 00022 POINTL* BrushOrigin, 00023 ROP4 Rop4); 00024 00025 static BOOLEAN APIENTRY 00026 CallDibStretchBlt(SURFOBJ* psoDest, 00027 SURFOBJ* psoSource, 00028 SURFOBJ* Mask, 00029 XLATEOBJ* ColorTranslation, 00030 RECTL* OutputRect, 00031 RECTL* InputRect, 00032 POINTL* MaskOrigin, 00033 BRUSHOBJ* pbo, 00034 POINTL* BrushOrigin, 00035 ROP4 Rop4) 00036 { 00037 POINTL RealBrushOrigin; 00038 SURFOBJ* psoPattern; 00039 BOOL bResult; 00040 00041 if (BrushOrigin == NULL) 00042 { 00043 RealBrushOrigin.x = RealBrushOrigin.y = 0; 00044 } 00045 else 00046 { 00047 RealBrushOrigin = *BrushOrigin; 00048 } 00049 00050 /* Pattern brush */ 00051 if (ROP4_USES_PATTERN(Rop4) && pbo && pbo->iSolidColor == 0xFFFFFFFF) 00052 { 00053 psoPattern = BRUSHOBJ_psoPattern(pbo); 00054 00055 if (!psoPattern) return FALSE; 00056 } 00057 else 00058 { 00059 psoPattern = NULL; 00060 } 00061 00062 bResult = DibFunctionsForBitmapFormat[psoDest->iBitmapFormat].DIB_StretchBlt( 00063 psoDest, psoSource, Mask, psoPattern, 00064 OutputRect, InputRect, MaskOrigin, pbo, &RealBrushOrigin, 00065 ColorTranslation, Rop4); 00066 00067 return bResult; 00068 } 00069 00070 00071 00072 /* 00073 * @implemented 00074 */ 00075 BOOL 00076 APIENTRY 00077 EngStretchBltROP( 00078 IN SURFOBJ *psoDest, 00079 IN SURFOBJ *psoSource, 00080 IN SURFOBJ *Mask, 00081 IN CLIPOBJ *ClipRegion, 00082 IN XLATEOBJ *ColorTranslation, 00083 IN COLORADJUSTMENT *pca, 00084 IN POINTL *BrushOrigin, 00085 IN RECTL *prclDest, 00086 IN RECTL *prclSrc, 00087 IN POINTL *MaskOrigin, 00088 IN ULONG Mode, 00089 IN BRUSHOBJ *pbo, 00090 IN ROP4 Rop4) 00091 { 00092 RECTL InputRect; 00093 RECTL OutputRect; 00094 POINTL Translate; 00095 INTENG_ENTER_LEAVE EnterLeaveSource; 00096 INTENG_ENTER_LEAVE EnterLeaveDest; 00097 SURFOBJ* psoInput; 00098 SURFOBJ* psoOutput; 00099 PSTRETCHRECTFUNC BltRectFunc; 00100 BOOLEAN Ret = TRUE; 00101 POINTL AdjustedBrushOrigin; 00102 BOOL UsesSource = ROP4_USES_SOURCE(Rop4); 00103 00104 BYTE clippingType; 00105 RECTL ClipRect; 00106 RECT_ENUM RectEnum; 00107 BOOL EnumMore; 00108 ULONG Direction; 00109 RECTL CombinedRect; 00110 RECTL InputToCombinedRect; 00111 unsigned i; 00112 00113 LONG DstHeight; 00114 LONG DstWidth; 00115 LONG SrcHeight; 00116 LONG SrcWidth; 00117 00118 if (Rop4 == ROP4_NOOP) 00119 { 00120 /* Copy destination onto itself: nop */ 00121 return TRUE; 00122 } 00123 00124 00125 /* Determine clipping type */ 00126 if (ClipRegion == (CLIPOBJ *) NULL) 00127 { 00128 clippingType = DC_TRIVIAL; 00129 } 00130 else 00131 { 00132 clippingType = ClipRegion->iDComplexity; 00133 } 00134 00135 OutputRect = *prclDest; 00136 if (OutputRect.right < OutputRect.left) 00137 { 00138 OutputRect.left = prclDest->right; 00139 OutputRect.right = prclDest->left; 00140 } 00141 if (OutputRect.bottom < OutputRect.top) 00142 { 00143 OutputRect.top = prclDest->bottom; 00144 OutputRect.bottom = prclDest->top; 00145 } 00146 00147 if (UsesSource) 00148 { 00149 if (NULL == prclSrc) 00150 { 00151 return FALSE; 00152 } 00153 InputRect = *prclSrc; 00154 00155 if (! IntEngEnter(&EnterLeaveSource, psoSource, &InputRect, TRUE, 00156 &Translate, &psoInput)) 00157 { 00158 return FALSE; 00159 } 00160 00161 InputRect.left += Translate.x; 00162 InputRect.right += Translate.x; 00163 InputRect.top += Translate.y; 00164 InputRect.bottom += Translate.y; 00165 } 00166 else 00167 { 00168 InputRect.left = 0; 00169 InputRect.right = OutputRect.right - OutputRect.left; 00170 InputRect.top = 0; 00171 InputRect.bottom = OutputRect.bottom - OutputRect.top; 00172 } 00173 00174 if (NULL != ClipRegion) 00175 { 00176 if (OutputRect.left < ClipRegion->rclBounds.left) 00177 { 00178 InputRect.left += ClipRegion->rclBounds.left - OutputRect.left; 00179 OutputRect.left = ClipRegion->rclBounds.left; 00180 } 00181 if (ClipRegion->rclBounds.right < OutputRect.right) 00182 { 00183 InputRect.right -= OutputRect.right - ClipRegion->rclBounds.right; 00184 OutputRect.right = ClipRegion->rclBounds.right; 00185 } 00186 if (OutputRect.top < ClipRegion->rclBounds.top) 00187 { 00188 InputRect.top += ClipRegion->rclBounds.top - OutputRect.top; 00189 OutputRect.top = ClipRegion->rclBounds.top; 00190 } 00191 if (ClipRegion->rclBounds.bottom < OutputRect.bottom) 00192 { 00193 InputRect.bottom -= OutputRect.bottom - ClipRegion->rclBounds.bottom; 00194 OutputRect.bottom = ClipRegion->rclBounds.bottom; 00195 } 00196 } 00197 00198 /* Check for degenerate case: if height or width of OutputRect is 0 pixels there's 00199 nothing to do */ 00200 if (OutputRect.right <= OutputRect.left || OutputRect.bottom <= OutputRect.top) 00201 { 00202 if (UsesSource) 00203 { 00204 IntEngLeave(&EnterLeaveSource); 00205 } 00206 return TRUE; 00207 } 00208 00209 if (! IntEngEnter(&EnterLeaveDest, psoDest, &OutputRect, FALSE, &Translate, &psoOutput)) 00210 { 00211 if (UsesSource) 00212 { 00213 IntEngLeave(&EnterLeaveSource); 00214 } 00215 return FALSE; 00216 } 00217 00218 OutputRect.left += Translate.x; 00219 OutputRect.right += Translate.x; 00220 OutputRect.top += Translate.y; 00221 OutputRect.bottom += Translate.y; 00222 00223 if (BrushOrigin) 00224 { 00225 AdjustedBrushOrigin.x = BrushOrigin->x + Translate.x; 00226 AdjustedBrushOrigin.y = BrushOrigin->y + Translate.y; 00227 } 00228 else 00229 { 00230 AdjustedBrushOrigin = Translate; 00231 } 00232 00233 BltRectFunc = CallDibStretchBlt; 00234 00235 DstHeight = OutputRect.bottom - OutputRect.top; 00236 DstWidth = OutputRect.right - OutputRect.left; 00237 SrcHeight = InputRect.bottom - InputRect.top; 00238 SrcWidth = InputRect.right - InputRect.left; 00239 switch (clippingType) 00240 { 00241 case DC_TRIVIAL: 00242 Ret = (*BltRectFunc)(psoOutput, psoInput, Mask, 00243 ColorTranslation, &OutputRect, &InputRect, MaskOrigin, 00244 pbo, &AdjustedBrushOrigin, Rop4); 00245 break; 00246 case DC_RECT: 00247 // Clip the blt to the clip rectangle 00248 ClipRect.left = ClipRegion->rclBounds.left + Translate.x; 00249 ClipRect.right = ClipRegion->rclBounds.right + Translate.x; 00250 ClipRect.top = ClipRegion->rclBounds.top + Translate.y; 00251 ClipRect.bottom = ClipRegion->rclBounds.bottom + Translate.y; 00252 if (RECTL_bIntersectRect(&CombinedRect, &OutputRect, &ClipRect)) 00253 { 00254 InputToCombinedRect.top = InputRect.top + (CombinedRect.top - OutputRect.top) * SrcHeight / DstHeight; 00255 InputToCombinedRect.bottom = InputRect.top + (CombinedRect.bottom - OutputRect.top) * SrcHeight / DstHeight; 00256 InputToCombinedRect.left = InputRect.left + (CombinedRect.left - OutputRect.left) * SrcWidth / DstWidth; 00257 InputToCombinedRect.right = InputRect.left + (CombinedRect.right - OutputRect.left) * SrcWidth / DstWidth; 00258 Ret = (*BltRectFunc)(psoOutput, psoInput, Mask, 00259 ColorTranslation, 00260 &CombinedRect, 00261 &InputToCombinedRect, 00262 MaskOrigin, 00263 pbo, 00264 &AdjustedBrushOrigin, 00265 Rop4); 00266 } 00267 break; 00268 case DC_COMPLEX: 00269 if (psoOutput == psoInput) 00270 { 00271 if (OutputRect.top < InputRect.top) 00272 { 00273 Direction = OutputRect.left < InputRect.left ? 00274 CD_RIGHTDOWN : CD_LEFTDOWN; 00275 } 00276 else 00277 { 00278 Direction = OutputRect.left < InputRect.left ? 00279 CD_RIGHTUP : CD_LEFTUP; 00280 } 00281 } 00282 else 00283 { 00284 Direction = CD_ANY; 00285 } 00286 CLIPOBJ_cEnumStart(ClipRegion, FALSE, CT_RECTANGLES, Direction, 0); 00287 do 00288 { 00289 EnumMore = CLIPOBJ_bEnum(ClipRegion,(ULONG) sizeof(RectEnum), 00290 (PVOID) &RectEnum); 00291 for (i = 0; i < RectEnum.c; i++) 00292 { 00293 ClipRect.left = RectEnum.arcl[i].left + Translate.x; 00294 ClipRect.right = RectEnum.arcl[i].right + Translate.x; 00295 ClipRect.top = RectEnum.arcl[i].top + Translate.y; 00296 ClipRect.bottom = RectEnum.arcl[i].bottom + Translate.y; 00297 if (RECTL_bIntersectRect(&CombinedRect, &OutputRect, &ClipRect)) 00298 { 00299 InputToCombinedRect.top = InputRect.top + (CombinedRect.top - OutputRect.top) * SrcHeight / DstHeight; 00300 InputToCombinedRect.bottom = InputRect.top + (CombinedRect.bottom - OutputRect.top) * SrcHeight / DstHeight; 00301 InputToCombinedRect.left = InputRect.left + (CombinedRect.left - OutputRect.left) * SrcWidth / DstWidth; 00302 InputToCombinedRect.right = InputRect.left + (CombinedRect.right - OutputRect.left) * SrcWidth / DstWidth; 00303 Ret = (*BltRectFunc)(psoOutput, psoInput, Mask, 00304 ColorTranslation, 00305 &CombinedRect, 00306 &InputToCombinedRect, 00307 MaskOrigin, 00308 pbo, 00309 &AdjustedBrushOrigin, 00310 Rop4); 00311 } 00312 } 00313 } 00314 while (EnumMore); 00315 break; 00316 } 00317 00318 IntEngLeave(&EnterLeaveDest); 00319 if (UsesSource) 00320 { 00321 IntEngLeave(&EnterLeaveSource); 00322 } 00323 00324 return Ret; 00325 } 00326 00327 /* 00328 * @implemented 00329 */ 00330 BOOL 00331 APIENTRY 00332 EngStretchBlt( 00333 IN SURFOBJ *psoDest, 00334 IN SURFOBJ *psoSource, 00335 IN SURFOBJ *Mask, 00336 IN CLIPOBJ *ClipRegion, 00337 IN XLATEOBJ *ColorTranslation, 00338 IN COLORADJUSTMENT *pca, 00339 IN POINTL *BrushOrigin, 00340 IN RECTL *prclDest, 00341 IN RECTL *prclSrc, 00342 IN POINTL *MaskOrigin, 00343 IN ULONG Mode) 00344 { 00345 return EngStretchBltROP( 00346 psoDest, 00347 psoSource, 00348 Mask, 00349 ClipRegion, 00350 ColorTranslation, 00351 pca, 00352 BrushOrigin, 00353 prclDest, 00354 prclSrc, 00355 MaskOrigin, 00356 Mode, 00357 NULL, 00358 ROP4_FROM_INDEX(R3_OPINDEX_SRCCOPY)); 00359 } 00360 00361 BOOL APIENTRY 00362 IntEngStretchBlt(SURFOBJ *psoDest, 00363 SURFOBJ *psoSource, 00364 SURFOBJ *MaskSurf, 00365 CLIPOBJ *ClipRegion, 00366 XLATEOBJ *ColorTranslation, 00367 RECTL *DestRect, 00368 RECTL *SourceRect, 00369 POINTL *pMaskOrigin, 00370 BRUSHOBJ *pbo, 00371 POINTL *BrushOrigin, 00372 DWORD Rop4) 00373 { 00374 BOOLEAN ret; 00375 COLORADJUSTMENT ca; 00376 POINTL MaskOrigin = {0, 0}; 00377 SURFACE *psurfDest; 00378 //SURFACE *psurfSource = NULL; 00379 RECTL InputClippedRect; 00380 RECTL InputRect; 00381 RECTL OutputRect; 00382 BOOL UsesSource = ROP4_USES_SOURCE(Rop4); 00383 LONG InputClWidth, InputClHeight, InputWidth, InputHeight; 00384 00385 ASSERT(psoDest); 00386 psurfDest = CONTAINING_RECORD(psoDest, SURFACE, SurfObj); 00387 ASSERT(psurfDest); 00388 ASSERT(DestRect); 00389 00390 /* Sanity check */ 00391 ASSERT(IS_VALID_ROP4(Rop4)); 00392 00393 /* Check if source and dest size are equal */ 00394 if (((DestRect->right - DestRect->left) == (SourceRect->right - SourceRect->left)) && 00395 ((DestRect->bottom - DestRect->top) == (SourceRect->bottom - SourceRect->top))) 00396 { 00397 /* Pass the request to IntEngBitBlt */ 00398 return IntEngBitBlt(psoDest, 00399 psoSource, 00400 MaskSurf, 00401 ClipRegion, 00402 ColorTranslation, 00403 DestRect, 00404 (PPOINTL)SourceRect, 00405 pMaskOrigin, 00406 pbo, 00407 BrushOrigin, 00408 Rop4); 00409 } 00410 00411 InputClippedRect = *DestRect; 00412 if (InputClippedRect.right < InputClippedRect.left) 00413 { 00414 InputClippedRect.left = DestRect->right; 00415 InputClippedRect.right = DestRect->left; 00416 } 00417 if (InputClippedRect.bottom < InputClippedRect.top) 00418 { 00419 InputClippedRect.top = DestRect->bottom; 00420 InputClippedRect.bottom = DestRect->top; 00421 } 00422 00423 if (UsesSource) 00424 { 00425 if (NULL == SourceRect || NULL == psoSource) 00426 { 00427 return FALSE; 00428 } 00429 InputRect = *SourceRect; 00430 00431 if (InputRect.right < InputRect.left || 00432 InputRect.bottom < InputRect.top) 00433 { 00434 /* Everything clipped away, nothing to do */ 00435 return TRUE; 00436 } 00437 } 00438 00439 if (ClipRegion) 00440 { 00441 if (!RECTL_bIntersectRect(&OutputRect, &InputClippedRect, 00442 &ClipRegion->rclBounds)) 00443 { 00444 return TRUE; 00445 } 00446 /* Update source rect */ 00447 InputClWidth = InputClippedRect.right - InputClippedRect.left; 00448 InputClHeight = InputClippedRect.bottom - InputClippedRect.top; 00449 InputWidth = InputRect.right - InputRect.left; 00450 InputHeight = InputRect.bottom - InputRect.top; 00451 00452 InputRect.left += (InputWidth * (OutputRect.left - InputClippedRect.left)) / InputClWidth; 00453 InputRect.right -= (InputWidth * (InputClippedRect.right - OutputRect.right)) / InputClWidth; 00454 InputRect.top += (InputHeight * (OutputRect.top - InputClippedRect.top)) / InputClHeight; 00455 InputRect.bottom -= (InputHeight * (InputClippedRect.bottom - OutputRect.bottom)) / InputClHeight; 00456 } 00457 else 00458 { 00459 OutputRect = InputClippedRect; 00460 } 00461 00462 if (pMaskOrigin != NULL) 00463 { 00464 MaskOrigin.x = pMaskOrigin->x; 00465 MaskOrigin.y = pMaskOrigin->y; 00466 } 00467 00468 /* No success yet */ 00469 ret = FALSE; 00470 00471 if (UsesSource) 00472 { 00473 //psurfSource = CONTAINING_RECORD(psoSource, SURFACE, SurfObj); 00474 } 00475 00476 /* Prepare color adjustment */ 00477 00478 /* Call the driver's DrvStretchBlt if available */ 00479 if (psurfDest->flags & HOOK_STRETCHBLTROP) 00480 { 00481 /* Drv->StretchBltROP (look at http://www.osronline.com/ddkx/graphics/ddifncs_0z3b.htm ) */ 00482 ret = GDIDEVFUNCS(psoDest).StretchBltROP(psoDest, 00483 (UsesSource) ? psoSource : NULL, 00484 MaskSurf, 00485 ClipRegion, 00486 ColorTranslation, 00487 &ca, BrushOrigin, 00488 &OutputRect, 00489 &InputRect, 00490 &MaskOrigin, 00491 COLORONCOLOR, 00492 pbo, 00493 Rop4); 00494 } 00495 00496 if (! ret) 00497 { 00498 ret = EngStretchBltROP(psoDest, 00499 (UsesSource) ? psoSource : NULL, 00500 MaskSurf, 00501 ClipRegion, 00502 ColorTranslation, 00503 &ca, 00504 BrushOrigin, 00505 &OutputRect, 00506 &InputRect, 00507 &MaskOrigin, 00508 COLORONCOLOR, 00509 pbo, 00510 Rop4); 00511 } 00512 00513 return ret; 00514 } 00515 00516 BOOL 00517 APIENTRY 00518 NtGdiEngStretchBlt( 00519 IN SURFOBJ *psoDest, 00520 IN SURFOBJ *psoSource, 00521 IN SURFOBJ *Mask, 00522 IN CLIPOBJ *ClipRegion, 00523 IN XLATEOBJ *ColorTranslation, 00524 IN COLORADJUSTMENT *pca, 00525 IN POINTL *BrushOrigin, 00526 IN RECTL *prclDest, 00527 IN RECTL *prclSrc, 00528 IN POINTL *MaskOrigin, 00529 IN ULONG Mode) 00530 { 00531 COLORADJUSTMENT ca; 00532 POINTL lBrushOrigin; 00533 RECTL rclDest; 00534 RECTL rclSrc; 00535 POINTL lMaskOrigin; 00536 00537 _SEH2_TRY 00538 { 00539 ProbeForRead(pca, sizeof(COLORADJUSTMENT), 1); 00540 RtlCopyMemory(&ca,pca, sizeof(COLORADJUSTMENT)); 00541 00542 ProbeForRead(BrushOrigin, sizeof(POINTL), 1); 00543 RtlCopyMemory(&lBrushOrigin, BrushOrigin, sizeof(POINTL)); 00544 00545 ProbeForRead(prclDest, sizeof(RECTL), 1); 00546 RtlCopyMemory(&rclDest, prclDest, sizeof(RECTL)); 00547 00548 ProbeForRead(prclSrc, sizeof(RECTL), 1); 00549 RtlCopyMemory(&rclSrc, prclSrc, sizeof(RECTL)); 00550 00551 ProbeForRead(MaskOrigin, sizeof(POINTL), 1); 00552 RtlCopyMemory(&lMaskOrigin, MaskOrigin, sizeof(POINTL)); 00553 00554 } 00555 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) 00556 { 00557 _SEH2_YIELD(return FALSE); 00558 } 00559 _SEH2_END; 00560 00561 return EngStretchBlt(psoDest, psoSource, Mask, ClipRegion, ColorTranslation, &ca, &lBrushOrigin, &rclDest, &rclSrc, &lMaskOrigin, Mode); 00562 } 00563 00564 /* EOF */ Generated on Sat May 26 2012 04:36:59 for ReactOS by
1.7.6.1
|