2 * DIB driver initialization and DC functions.
4 * Copyright 2011 Huw Davies
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
23 #include "gdi_private.h"
26 #include "wine/exception.h"
27 #include "wine/debug.h"
29 WINE_DEFAULT_DEBUG_CHANNEL(dib
);
31 static const DWORD bit_fields_888
[3] = {0xff0000, 0x00ff00, 0x0000ff};
32 static const DWORD bit_fields_555
[3] = {0x7c00, 0x03e0, 0x001f};
34 static void calc_shift_and_len(DWORD mask
, int *shift
, int *len
)
45 while ((mask
& 1) == 0)
51 while ((mask
& 1) == 1)
60 static void init_bit_fields(dib_info
*dib
, const DWORD
*bit_fields
)
62 dib
->red_mask
= bit_fields
[0];
63 dib
->green_mask
= bit_fields
[1];
64 dib
->blue_mask
= bit_fields
[2];
65 calc_shift_and_len(dib
->red_mask
, &dib
->red_shift
, &dib
->red_len
);
66 calc_shift_and_len(dib
->green_mask
, &dib
->green_shift
, &dib
->green_len
);
67 calc_shift_and_len(dib
->blue_mask
, &dib
->blue_shift
, &dib
->blue_len
);
70 static void init_dib_info(dib_info
*dib
, const BITMAPINFOHEADER
*bi
, int stride
,
71 const DWORD
*bit_fields
, const RGBQUAD
*color_table
, void *bits
)
73 dib
->bit_count
= bi
->biBitCount
;
74 dib
->width
= bi
->biWidth
;
75 dib
->height
= bi
->biHeight
;
78 dib
->rect
.right
= bi
->biWidth
;
79 dib
->rect
.bottom
= abs( bi
->biHeight
);
80 dib
->compression
= bi
->biCompression
;
83 dib
->bits
.is_copy
= FALSE
;
84 dib
->bits
.free
= NULL
;
85 dib
->bits
.param
= NULL
;
87 if(dib
->height
< 0) /* top-down */
89 dib
->height
= -dib
->height
;
93 /* bits always points to the top-left corner and the stride is -ve */
94 dib
->bits
.ptr
= (BYTE
*)dib
->bits
.ptr
+ (dib
->height
- 1) * dib
->stride
;
95 dib
->stride
= -dib
->stride
;
98 dib
->funcs
= &funcs_null
;
100 switch(dib
->bit_count
)
103 if(bi
->biCompression
== BI_RGB
)
104 bit_fields
= bit_fields_888
;
106 init_bit_fields(dib
, bit_fields
);
108 if(dib
->red_mask
== 0xff0000 && dib
->green_mask
== 0x00ff00 && dib
->blue_mask
== 0x0000ff)
109 dib
->funcs
= &funcs_8888
;
111 dib
->funcs
= &funcs_32
;
115 dib
->funcs
= &funcs_24
;
119 if(bi
->biCompression
== BI_RGB
)
120 bit_fields
= bit_fields_555
;
122 init_bit_fields(dib
, bit_fields
);
124 if(dib
->red_mask
== 0x7c00 && dib
->green_mask
== 0x03e0 && dib
->blue_mask
== 0x001f)
125 dib
->funcs
= &funcs_555
;
127 dib
->funcs
= &funcs_16
;
131 dib
->funcs
= &funcs_8
;
135 dib
->funcs
= &funcs_4
;
139 dib
->funcs
= &funcs_1
;
143 if (color_table
&& bi
->biClrUsed
)
145 dib
->color_table
= color_table
;
146 dib
->color_table_size
= bi
->biClrUsed
;
150 dib
->color_table
= NULL
;
151 dib
->color_table_size
= 0;
155 void init_dib_info_from_bitmapinfo(dib_info
*dib
, const BITMAPINFO
*info
, void *bits
)
157 int width_bytes
= get_dib_stride( info
->bmiHeader
.biWidth
, info
->bmiHeader
.biBitCount
);
158 if (info
->bmiHeader
.biSizeImage
)
159 width_bytes
= info
->bmiHeader
.biSizeImage
/ abs( info
->bmiHeader
.biHeight
);
160 init_dib_info( dib
, &info
->bmiHeader
, width_bytes
,
161 (const DWORD
*)info
->bmiColors
, info
->bmiColors
, bits
);
164 BOOL
init_dib_info_from_bitmapobj(dib_info
*dib
, BITMAPOBJ
*bmp
)
166 if (!is_bitmapobj_dib( bmp
))
170 get_ddb_bitmapinfo( bmp
, &info
);
171 init_dib_info_from_bitmapinfo( dib
, &info
, bmp
->dib
.dsBm
.bmBits
);
173 else init_dib_info( dib
, &bmp
->dib
.dsBmih
, bmp
->dib
.dsBm
.bmWidthBytes
,
174 bmp
->dib
.dsBitfields
, bmp
->color_table
, bmp
->dib
.dsBm
.bmBits
);
178 static void clear_dib_info(dib_info
*dib
)
180 dib
->bits
.ptr
= NULL
;
181 dib
->bits
.free
= NULL
;
182 dib
->bits
.param
= NULL
;
185 /**********************************************************************
188 * Free the resources associated with a dib and optionally the bits
190 void free_dib_info(dib_info
*dib
)
192 if (dib
->bits
.free
) dib
->bits
.free( &dib
->bits
);
193 clear_dib_info( dib
);
196 void copy_dib_color_info(dib_info
*dst
, const dib_info
*src
)
198 dst
->bit_count
= src
->bit_count
;
199 dst
->red_mask
= src
->red_mask
;
200 dst
->green_mask
= src
->green_mask
;
201 dst
->blue_mask
= src
->blue_mask
;
202 dst
->red_len
= src
->red_len
;
203 dst
->green_len
= src
->green_len
;
204 dst
->blue_len
= src
->blue_len
;
205 dst
->red_shift
= src
->red_shift
;
206 dst
->green_shift
= src
->green_shift
;
207 dst
->blue_shift
= src
->blue_shift
;
208 dst
->funcs
= src
->funcs
;
209 dst
->color_table_size
= src
->color_table_size
;
210 dst
->color_table
= src
->color_table
;
213 DWORD
convert_bitmapinfo( const BITMAPINFO
*src_info
, void *src_bits
, struct bitblt_coords
*src
,
214 const BITMAPINFO
*dst_info
, void *dst_bits
)
216 dib_info src_dib
, dst_dib
;
219 init_dib_info_from_bitmapinfo( &src_dib
, src_info
, src_bits
);
220 init_dib_info_from_bitmapinfo( &dst_dib
, dst_info
, dst_bits
);
224 dst_dib
.funcs
->convert_to( &dst_dib
, &src_dib
, &src
->visrect
, FALSE
);
229 WARN( "invalid bits pointer %p\n", src_bits
);
234 if(!ret
) return ERROR_BAD_FORMAT
;
236 /* update coordinates, the destination rectangle is always stored at 0,0 */
237 src
->x
-= src
->visrect
.left
;
238 src
->y
-= src
->visrect
.top
;
239 offset_rect( &src
->visrect
, -src
->visrect
.left
, -src
->visrect
.top
);
240 return ERROR_SUCCESS
;
243 int get_dib_rect( const dib_info
*dib
, RECT
*rc
)
245 rc
->left
= max( 0, -dib
->rect
.left
);
246 rc
->top
= max( 0, -dib
->rect
.top
);
247 rc
->right
= min( dib
->rect
.right
, dib
->width
) - dib
->rect
.left
;
248 rc
->bottom
= min( dib
->rect
.bottom
, dib
->height
) - dib
->rect
.top
;
249 return !is_rect_empty( rc
);
252 int clip_rect_to_dib( const dib_info
*dib
, RECT
*rc
)
256 return get_dib_rect( dib
, &rect
) && intersect_rect( rc
, &rect
, rc
);
259 int get_clipped_rects( const dib_info
*dib
, const RECT
*rc
, HRGN clip
, struct clipped_rects
*clip_rects
)
261 const WINEREGION
*region
;
262 RECT rect
, *out
= clip_rects
->buffer
;
265 init_clipped_rects( clip_rects
);
267 if (!get_dib_rect( dib
, &rect
)) return 0;
268 if (rc
&& !intersect_rect( &rect
, &rect
, rc
)) return 0;
273 clip_rects
->count
= 1;
277 if (!(region
= get_wine_region( clip
))) return 0;
279 for (i
= region_find_pt( region
, rect
.left
, rect
.top
, NULL
); i
< region
->numRects
; i
++)
281 if (region
->rects
[i
].top
>= rect
.bottom
) break;
282 if (!intersect_rect( out
, &rect
, ®ion
->rects
[i
] )) continue;
284 if (out
== &clip_rects
->buffer
[sizeof(clip_rects
->buffer
) / sizeof(RECT
)])
286 clip_rects
->rects
= HeapAlloc( GetProcessHeap(), 0, region
->numRects
* sizeof(RECT
) );
287 if (!clip_rects
->rects
) return 0;
288 memcpy( clip_rects
->rects
, clip_rects
->buffer
, (out
- clip_rects
->buffer
) * sizeof(RECT
) );
289 out
= clip_rects
->rects
+ (out
- clip_rects
->buffer
);
292 release_wine_region( clip
);
293 clip_rects
->count
= out
- clip_rects
->rects
;
294 return clip_rects
->count
;
297 void add_clipped_bounds( dibdrv_physdev
*dev
, const RECT
*rect
, HRGN clip
)
299 const WINEREGION
*region
;
302 if (!dev
->bounds
) return;
305 if (!(region
= get_wine_region( clip
))) return;
306 if (!rect
) rc
= region
->extents
;
307 else intersect_rect( &rc
, rect
, ®ion
->extents
);
308 release_wine_region( clip
);
312 if (is_rect_empty( &rc
)) return;
313 offset_rect( &rc
, dev
->dib
.rect
.left
, dev
->dib
.rect
.top
);
314 add_bounds_rect( dev
->bounds
, &rc
);
317 /**********************************************************************
320 static BOOL
dibdrv_CreateDC( PHYSDEV
*dev
, LPCWSTR driver
, LPCWSTR device
,
321 LPCWSTR output
, const DEVMODEW
*data
)
323 dibdrv_physdev
*pdev
= HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(*pdev
) );
325 if (!pdev
) return FALSE
;
326 clear_dib_info(&pdev
->dib
);
327 clear_dib_info(&pdev
->brush
.dib
);
328 clear_dib_info(&pdev
->pen_brush
.dib
);
329 push_dc_driver( dev
, &pdev
->dev
, &dib_driver
);
333 /***********************************************************************
336 static BOOL
dibdrv_DeleteDC( PHYSDEV dev
)
338 dibdrv_physdev
*pdev
= get_dibdrv_pdev(dev
);
339 TRACE("(%p)\n", dev
);
340 free_pattern_brush( &pdev
->brush
);
341 free_pattern_brush( &pdev
->pen_brush
);
342 release_cached_font( pdev
->font
);
343 HeapFree( GetProcessHeap(), 0, pdev
);
347 /***********************************************************************
348 * dibdrv_SelectBitmap
350 static HBITMAP
dibdrv_SelectBitmap( PHYSDEV dev
, HBITMAP bitmap
)
352 dibdrv_physdev
*pdev
= get_dibdrv_pdev(dev
);
353 BITMAPOBJ
*bmp
= GDI_GetObjPtr( bitmap
, OBJ_BITMAP
);
356 TRACE("(%p, %p)\n", dev
, bitmap
);
360 if (!init_dib_info_from_bitmapobj(&dib
, bmp
))
362 GDI_ReleaseObj( bitmap
);
366 GDI_ReleaseObj( bitmap
);
371 /***********************************************************************
372 * dibdrv_SetDeviceClipping
374 static void dibdrv_SetDeviceClipping( PHYSDEV dev
, HRGN rgn
)
376 dibdrv_physdev
*pdev
= get_dibdrv_pdev(dev
);
377 TRACE("(%p, %p)\n", dev
, rgn
);
382 /***********************************************************************
383 * dibdrv_SetBoundsRect
385 static UINT
dibdrv_SetBoundsRect( PHYSDEV dev
, RECT
*rect
, UINT flags
)
387 dibdrv_physdev
*pdev
= get_dibdrv_pdev( dev
);
389 if (flags
& DCB_DISABLE
) pdev
->bounds
= NULL
;
390 else if (flags
& DCB_ENABLE
) pdev
->bounds
= rect
;
391 return DCB_RESET
; /* we don't have device-specific bounds */
394 const struct gdi_dc_funcs dib_driver
=
396 NULL
, /* pAbortDoc */
397 NULL
, /* pAbortPath */
398 dibdrv_AlphaBlend
, /* pAlphaBlend */
399 NULL
, /* pAngleArc */
400 dibdrv_Arc
, /* pArc */
401 dibdrv_ArcTo
, /* pArcTo */
402 NULL
, /* pBeginPath */
403 dibdrv_BlendImage
, /* pBlendImage */
404 dibdrv_Chord
, /* pChord */
405 NULL
, /* pCloseFigure */
406 NULL
, /* pCreateCompatibleDC */
407 dibdrv_CreateDC
, /* pCreateDC */
408 dibdrv_DeleteDC
, /* pDeleteDC */
409 NULL
, /* pDeleteObject */
410 NULL
, /* pDeviceCapabilities */
411 dibdrv_Ellipse
, /* pEllipse */
415 NULL
, /* pEnumFonts */
416 NULL
, /* pEnumICMProfiles */
417 NULL
, /* pExcludeClipRect */
418 NULL
, /* pExtDeviceMode */
419 NULL
, /* pExtEscape */
420 dibdrv_ExtFloodFill
, /* pExtFloodFill */
421 NULL
, /* pExtSelectClipRgn */
422 dibdrv_ExtTextOut
, /* pExtTextOut */
423 dibdrv_FillPath
, /* pFillPath */
425 NULL
, /* pFlattenPath */
426 NULL
, /* pFontIsLinked */
427 NULL
, /* pFrameRgn */
428 NULL
, /* pGdiComment */
429 NULL
, /* pGetBoundsRect */
430 NULL
, /* pGetCharABCWidths */
431 NULL
, /* pGetCharABCWidthsI */
432 NULL
, /* pGetCharWidth */
433 NULL
, /* pGetDeviceCaps */
434 NULL
, /* pGetDeviceGammaRamp */
435 NULL
, /* pGetFontData */
436 NULL
, /* pGetFontRealizationInfo */
437 NULL
, /* pGetFontUnicodeRanges */
438 NULL
, /* pGetGlyphIndices */
439 NULL
, /* pGetGlyphOutline */
440 NULL
, /* pGetICMProfile */
441 dibdrv_GetImage
, /* pGetImage */
442 NULL
, /* pGetKerningPairs */
443 dibdrv_GetNearestColor
, /* pGetNearestColor */
444 NULL
, /* pGetOutlineTextMetrics */
445 dibdrv_GetPixel
, /* pGetPixel */
446 NULL
, /* pGetSystemPaletteEntries */
447 NULL
, /* pGetTextCharsetInfo */
448 NULL
, /* pGetTextExtentExPoint */
449 NULL
, /* pGetTextExtentExPointI */
450 NULL
, /* pGetTextFace */
451 NULL
, /* pGetTextMetrics */
452 dibdrv_GradientFill
, /* pGradientFill */
453 NULL
, /* pIntersectClipRect */
454 NULL
, /* pInvertRgn */
455 dibdrv_LineTo
, /* pLineTo */
456 NULL
, /* pModifyWorldTransform */
458 NULL
, /* pOffsetClipRgn */
459 NULL
, /* pOffsetViewportOrg */
460 NULL
, /* pOffsetWindowOrg */
461 dibdrv_PaintRgn
, /* pPaintRgn */
462 dibdrv_PatBlt
, /* pPatBlt */
463 dibdrv_Pie
, /* pPie */
464 NULL
, /* pPolyBezier */
465 NULL
, /* pPolyBezierTo */
466 NULL
, /* pPolyDraw */
467 dibdrv_PolyPolygon
, /* pPolyPolygon */
468 dibdrv_PolyPolyline
, /* pPolyPolyline */
469 dibdrv_Polygon
, /* pPolygon */
470 dibdrv_Polyline
, /* pPolyline */
471 NULL
, /* pPolylineTo */
472 dibdrv_PutImage
, /* pPutImage */
473 NULL
, /* pRealizeDefaultPalette */
474 NULL
, /* pRealizePalette */
475 dibdrv_Rectangle
, /* pRectangle */
477 NULL
, /* pRestoreDC */
478 dibdrv_RoundRect
, /* pRoundRect */
480 NULL
, /* pScaleViewportExt */
481 NULL
, /* pScaleWindowExt */
482 dibdrv_SelectBitmap
, /* pSelectBitmap */
483 dibdrv_SelectBrush
, /* pSelectBrush */
484 NULL
, /* pSelectClipPath */
485 dibdrv_SelectFont
, /* pSelectFont */
486 NULL
, /* pSelectPalette */
487 dibdrv_SelectPen
, /* pSelectPen */
488 NULL
, /* pSetArcDirection */
489 NULL
, /* pSetBkColor */
490 NULL
, /* pSetBkMode */
491 dibdrv_SetBoundsRect
, /* pSetBoundsRect */
492 dibdrv_SetDCBrushColor
, /* pSetDCBrushColor */
493 dibdrv_SetDCPenColor
, /* pSetDCPenColor */
494 NULL
, /* pSetDIBitsToDevice */
495 dibdrv_SetDeviceClipping
, /* pSetDeviceClipping */
496 NULL
, /* pSetDeviceGammaRamp */
497 NULL
, /* pSetLayout */
498 NULL
, /* pSetMapMode */
499 NULL
, /* pSetMapperFlags */
500 dibdrv_SetPixel
, /* pSetPixel */
501 NULL
, /* pSetPolyFillMode */
503 NULL
, /* pSetRelAbs */
504 NULL
, /* pSetStretchBltMode */
505 NULL
, /* pSetTextAlign */
506 NULL
, /* pSetTextCharacterExtra */
507 NULL
, /* pSetTextColor */
508 NULL
, /* pSetTextJustification */
509 NULL
, /* pSetViewportExt */
510 NULL
, /* pSetViewportOrg */
511 NULL
, /* pSetWindowExt */
512 NULL
, /* pSetWindowOrg */
513 NULL
, /* pSetWorldTransform */
514 NULL
, /* pStartDoc */
515 NULL
, /* pStartPage */
516 dibdrv_StretchBlt
, /* pStretchBlt */
517 NULL
, /* pStretchDIBits */
518 dibdrv_StrokeAndFillPath
, /* pStrokeAndFillPath */
519 dibdrv_StrokePath
, /* pStrokePath */
520 NULL
, /* pUnrealizePalette */
521 NULL
, /* pWidenPath */
522 dibdrv_wine_get_wgl_driver
, /* wine_get_wgl_driver */
523 NULL
, /* wine_get_vulkan_driver */
524 GDI_PRIORITY_DIB_DRV
/* priority */
528 /***********************************************************************
529 * Driver for window surfaces.
531 * It uses the DIB engine but needs extra locking since multiple DCs
532 * can paint to the same window.
535 #define FLUSH_PERIOD 50 /* time in ms since drawing started for forcing a surface flush */
537 struct windrv_physdev
539 struct gdi_physdev dev
;
540 struct dibdrv_physdev
*dibdrv
;
541 struct window_surface
*surface
;
545 static const struct gdi_dc_funcs window_driver
;
547 static inline struct windrv_physdev
*get_windrv_physdev( PHYSDEV dev
)
549 return (struct windrv_physdev
*)dev
;
552 static inline void lock_surface( struct windrv_physdev
*dev
)
555 dev
->surface
->funcs
->lock( dev
->surface
);
556 if (is_rect_empty( dev
->dibdrv
->bounds
)) dev
->start_ticks
= GetTickCount();
559 static inline void unlock_surface( struct windrv_physdev
*dev
)
561 dev
->surface
->funcs
->unlock( dev
->surface
);
562 if (GetTickCount() - dev
->start_ticks
> FLUSH_PERIOD
) dev
->surface
->funcs
->flush( dev
->surface
);
565 static void unlock_bits_surface( struct gdi_image_bits
*bits
)
567 struct window_surface
*surface
= bits
->param
;
568 surface
->funcs
->unlock( surface
);
571 void dibdrv_set_window_surface( DC
*dc
, struct window_surface
*surface
)
573 char buffer
[FIELD_OFFSET( BITMAPINFO
, bmiColors
[256] )];
574 BITMAPINFO
*info
= (BITMAPINFO
*)buffer
;
577 struct windrv_physdev
*physdev
;
578 struct dibdrv_physdev
*dibdrv
;
580 TRACE( "%p %p\n", dc
->hSelf
, surface
);
582 windev
= pop_dc_driver( dc
, &window_driver
);
586 if (windev
) push_dc_driver( &dc
->physDev
, windev
, windev
->funcs
);
589 if (!window_driver
.pCreateDC( &dc
->physDev
, NULL
, NULL
, NULL
, NULL
)) return;
590 windev
= find_dc_driver( dc
, &window_driver
);
593 physdev
= get_windrv_physdev( windev
);
594 window_surface_add_ref( surface
);
595 if (physdev
->surface
) window_surface_release( physdev
->surface
);
596 physdev
->surface
= surface
;
598 dibdrv
= physdev
->dibdrv
;
599 bits
= surface
->funcs
->get_info( surface
, info
);
600 init_dib_info_from_bitmapinfo( &dibdrv
->dib
, info
, bits
);
601 dibdrv
->dib
.rect
= dc
->vis_rect
;
602 offset_rect( &dibdrv
->dib
.rect
, -dc
->device_rect
.left
, -dc
->device_rect
.top
);
603 dibdrv
->bounds
= surface
->funcs
->get_bounds( surface
);
608 dib_driver
.pDeleteDC( pop_dc_driver( dc
, &dib_driver
));
609 windev
->funcs
->pDeleteDC( windev
);
614 static BOOL
windrv_AlphaBlend( PHYSDEV dst_dev
, struct bitblt_coords
*dst
,
615 PHYSDEV src_dev
, struct bitblt_coords
*src
, BLENDFUNCTION func
)
617 struct windrv_physdev
*physdev
= get_windrv_physdev( dst_dev
);
620 lock_surface( physdev
);
621 dst_dev
= GET_NEXT_PHYSDEV( dst_dev
, pAlphaBlend
);
622 ret
= dst_dev
->funcs
->pAlphaBlend( dst_dev
, dst
, src_dev
, src
, func
);
623 unlock_surface( physdev
);
627 static BOOL
windrv_Arc( PHYSDEV dev
, INT left
, INT top
, INT right
, INT bottom
,
628 INT xstart
, INT ystart
, INT xend
, INT yend
)
630 struct windrv_physdev
*physdev
= get_windrv_physdev( dev
);
633 lock_surface( physdev
);
634 dev
= GET_NEXT_PHYSDEV( dev
, pArc
);
635 ret
= dev
->funcs
->pArc( dev
, left
, top
, right
, bottom
, xstart
, ystart
, xend
, yend
);
636 unlock_surface( physdev
);
640 static BOOL
windrv_ArcTo( PHYSDEV dev
, INT left
, INT top
, INT right
, INT bottom
,
641 INT xstart
, INT ystart
, INT xend
, INT yend
)
643 struct windrv_physdev
*physdev
= get_windrv_physdev( dev
);
646 lock_surface( physdev
);
647 dev
= GET_NEXT_PHYSDEV( dev
, pArc
);
648 ret
= dev
->funcs
->pArcTo( dev
, left
, top
, right
, bottom
, xstart
, ystart
, xend
, yend
);
649 unlock_surface( physdev
);
653 static DWORD
windrv_BlendImage( PHYSDEV dev
, BITMAPINFO
*info
, const struct gdi_image_bits
*bits
,
654 struct bitblt_coords
*src
, struct bitblt_coords
*dst
, BLENDFUNCTION blend
)
656 struct windrv_physdev
*physdev
= get_windrv_physdev( dev
);
659 lock_surface( physdev
);
660 dev
= GET_NEXT_PHYSDEV( dev
, pBlendImage
);
661 ret
= dev
->funcs
->pBlendImage( dev
, info
, bits
, src
, dst
, blend
);
662 unlock_surface( physdev
);
666 static BOOL
windrv_Chord( PHYSDEV dev
, INT left
, INT top
, INT right
, INT bottom
,
667 INT xstart
, INT ystart
, INT xend
, INT yend
)
669 struct windrv_physdev
*physdev
= get_windrv_physdev( dev
);
672 lock_surface( physdev
);
673 dev
= GET_NEXT_PHYSDEV( dev
, pChord
);
674 ret
= dev
->funcs
->pChord( dev
, left
, top
, right
, bottom
, xstart
, ystart
, xend
, yend
);
675 unlock_surface( physdev
);
679 static BOOL
windrv_CreateDC( PHYSDEV
*dev
, LPCWSTR driver
, LPCWSTR device
,
680 LPCWSTR output
, const DEVMODEW
*devmode
)
682 struct windrv_physdev
*physdev
= HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(*physdev
) );
684 if (!physdev
) return FALSE
;
686 if (!dib_driver
.pCreateDC( dev
, NULL
, NULL
, NULL
, NULL
))
688 HeapFree( GetProcessHeap(), 0, physdev
);
691 physdev
->dibdrv
= get_dibdrv_pdev( *dev
);
692 push_dc_driver( dev
, &physdev
->dev
, &window_driver
);
696 static BOOL
windrv_DeleteDC( PHYSDEV dev
)
698 struct windrv_physdev
*physdev
= get_windrv_physdev( dev
);
700 window_surface_release( physdev
->surface
);
701 HeapFree( GetProcessHeap(), 0, physdev
);
705 static BOOL
windrv_Ellipse( PHYSDEV dev
, INT left
, INT top
, INT right
, INT bottom
)
707 struct windrv_physdev
*physdev
= get_windrv_physdev( dev
);
710 lock_surface( physdev
);
711 dev
= GET_NEXT_PHYSDEV( dev
, pEllipse
);
712 ret
= dev
->funcs
->pEllipse( dev
, left
, top
, right
, bottom
);
713 unlock_surface( physdev
);
717 static BOOL
windrv_ExtFloodFill( PHYSDEV dev
, INT x
, INT y
, COLORREF color
, UINT type
)
719 struct windrv_physdev
*physdev
= get_windrv_physdev( dev
);
722 lock_surface( physdev
);
723 dev
= GET_NEXT_PHYSDEV( dev
, pExtFloodFill
);
724 ret
= dev
->funcs
->pExtFloodFill( dev
, x
, y
, color
, type
);
725 unlock_surface( physdev
);
729 static BOOL
windrv_ExtTextOut( PHYSDEV dev
, INT x
, INT y
, UINT flags
, const RECT
*rect
,
730 LPCWSTR str
, UINT count
, const INT
*dx
)
732 struct windrv_physdev
*physdev
= get_windrv_physdev( dev
);
735 lock_surface( physdev
);
736 dev
= GET_NEXT_PHYSDEV( dev
, pExtTextOut
);
737 ret
= dev
->funcs
->pExtTextOut( dev
, x
, y
, flags
, rect
, str
, count
, dx
);
738 unlock_surface( physdev
);
742 static DWORD
windrv_GetImage( PHYSDEV dev
, BITMAPINFO
*info
,
743 struct gdi_image_bits
*bits
, struct bitblt_coords
*src
)
745 struct windrv_physdev
*physdev
= get_windrv_physdev( dev
);
748 lock_surface( physdev
);
749 dev
= GET_NEXT_PHYSDEV( dev
, pGetImage
);
750 ret
= dev
->funcs
->pGetImage( dev
, info
, bits
, src
);
752 /* don't return alpha if original surface doesn't support it */
753 if (info
->bmiHeader
.biBitCount
== 32 &&
754 info
->bmiHeader
.biCompression
== BI_RGB
&&
755 physdev
->dibdrv
->dib
.compression
== BI_BITFIELDS
)
757 DWORD
*colors
= (DWORD
*)info
->bmiColors
;
758 colors
[0] = 0xff0000;
759 colors
[1] = 0x00ff00;
760 colors
[2] = 0x0000ff;
761 info
->bmiHeader
.biCompression
= BI_BITFIELDS
;
766 /* use the freeing callback to unlock the surface */
767 assert( !bits
->free
);
768 bits
->free
= unlock_bits_surface
;
769 bits
->param
= physdev
->surface
;
771 else unlock_surface( physdev
);
775 static COLORREF
windrv_GetPixel( PHYSDEV dev
, INT x
, INT y
)
777 struct windrv_physdev
*physdev
= get_windrv_physdev( dev
);
780 lock_surface( physdev
);
781 dev
= GET_NEXT_PHYSDEV( dev
, pGetPixel
);
782 ret
= dev
->funcs
->pGetPixel( dev
, x
, y
);
783 unlock_surface( physdev
);
787 static BOOL
windrv_GradientFill( PHYSDEV dev
, TRIVERTEX
*vert_array
, ULONG nvert
,
788 void * grad_array
, ULONG ngrad
, ULONG mode
)
790 struct windrv_physdev
*physdev
= get_windrv_physdev( dev
);
793 lock_surface( physdev
);
794 dev
= GET_NEXT_PHYSDEV( dev
, pGradientFill
);
795 ret
= dev
->funcs
->pGradientFill( dev
, vert_array
, nvert
, grad_array
, ngrad
, mode
);
796 unlock_surface( physdev
);
800 static BOOL
windrv_LineTo( PHYSDEV dev
, INT x
, INT y
)
802 struct windrv_physdev
*physdev
= get_windrv_physdev( dev
);
805 lock_surface( physdev
);
806 dev
= GET_NEXT_PHYSDEV( dev
, pLineTo
);
807 ret
= dev
->funcs
->pLineTo( dev
, x
, y
);
808 unlock_surface( physdev
);
812 static BOOL
windrv_PaintRgn( PHYSDEV dev
, HRGN rgn
)
814 struct windrv_physdev
*physdev
= get_windrv_physdev( dev
);
817 lock_surface( physdev
);
818 dev
= GET_NEXT_PHYSDEV( dev
, pPaintRgn
);
819 ret
= dev
->funcs
->pPaintRgn( dev
, rgn
);
820 unlock_surface( physdev
);
824 static BOOL
windrv_PatBlt( PHYSDEV dev
, struct bitblt_coords
*dst
, DWORD rop
)
826 struct windrv_physdev
*physdev
= get_windrv_physdev( dev
);
829 lock_surface( physdev
);
830 dev
= GET_NEXT_PHYSDEV( dev
, pPatBlt
);
831 ret
= dev
->funcs
->pPatBlt( dev
, dst
, rop
);
832 unlock_surface( physdev
);
836 static BOOL
windrv_Pie( PHYSDEV dev
, INT left
, INT top
, INT right
, INT bottom
,
837 INT xstart
, INT ystart
, INT xend
, INT yend
)
839 struct windrv_physdev
*physdev
= get_windrv_physdev( dev
);
842 lock_surface( physdev
);
843 dev
= GET_NEXT_PHYSDEV( dev
, pPie
);
844 ret
= dev
->funcs
->pPie( dev
, left
, top
, right
, bottom
, xstart
, ystart
, xend
, yend
);
845 unlock_surface( physdev
);
849 static BOOL
windrv_PolyPolygon( PHYSDEV dev
, const POINT
*points
, const INT
*counts
, UINT polygons
)
851 struct windrv_physdev
*physdev
= get_windrv_physdev( dev
);
854 lock_surface( physdev
);
855 dev
= GET_NEXT_PHYSDEV( dev
, pPolyPolygon
);
856 ret
= dev
->funcs
->pPolyPolygon( dev
, points
, counts
, polygons
);
857 unlock_surface( physdev
);
861 static BOOL
windrv_PolyPolyline( PHYSDEV dev
, const POINT
*points
, const DWORD
*counts
, DWORD lines
)
863 struct windrv_physdev
*physdev
= get_windrv_physdev( dev
);
866 lock_surface( physdev
);
867 dev
= GET_NEXT_PHYSDEV( dev
, pPolyPolyline
);
868 ret
= dev
->funcs
->pPolyPolyline( dev
, points
, counts
, lines
);
869 unlock_surface( physdev
);
873 static BOOL
windrv_Polygon( PHYSDEV dev
, const POINT
*points
, INT count
)
875 struct windrv_physdev
*physdev
= get_windrv_physdev( dev
);
878 lock_surface( physdev
);
879 dev
= GET_NEXT_PHYSDEV( dev
, pPolygon
);
880 ret
= dev
->funcs
->pPolygon( dev
, points
, count
);
881 unlock_surface( physdev
);
885 static BOOL
windrv_Polyline( PHYSDEV dev
, const POINT
*points
, INT count
)
887 struct windrv_physdev
*physdev
= get_windrv_physdev( dev
);
890 lock_surface( physdev
);
891 dev
= GET_NEXT_PHYSDEV( dev
, pPolyline
);
892 ret
= dev
->funcs
->pPolyline( dev
, points
, count
);
893 unlock_surface( physdev
);
897 static DWORD
windrv_PutImage( PHYSDEV dev
, HRGN clip
, BITMAPINFO
*info
,
898 const struct gdi_image_bits
*bits
, struct bitblt_coords
*src
,
899 struct bitblt_coords
*dst
, DWORD rop
)
901 struct windrv_physdev
*physdev
= get_windrv_physdev( dev
);
904 lock_surface( physdev
);
905 dev
= GET_NEXT_PHYSDEV( dev
, pPutImage
);
906 ret
= dev
->funcs
->pPutImage( dev
, clip
, info
, bits
, src
, dst
, rop
);
907 unlock_surface( physdev
);
911 static BOOL
windrv_Rectangle( PHYSDEV dev
, INT left
, INT top
, INT right
, INT bottom
)
913 struct windrv_physdev
*physdev
= get_windrv_physdev( dev
);
916 lock_surface( physdev
);
917 dev
= GET_NEXT_PHYSDEV( dev
, pRectangle
);
918 ret
= dev
->funcs
->pRectangle( dev
, left
, top
, right
, bottom
);
919 unlock_surface( physdev
);
923 static BOOL
windrv_RoundRect( PHYSDEV dev
, INT left
, INT top
, INT right
, INT bottom
,
924 INT ell_width
, INT ell_height
)
926 struct windrv_physdev
*physdev
= get_windrv_physdev( dev
);
929 lock_surface( physdev
);
930 dev
= GET_NEXT_PHYSDEV( dev
, pRoundRect
);
931 ret
= dev
->funcs
->pRoundRect( dev
, left
, top
, right
, bottom
, ell_width
, ell_height
);
932 unlock_surface( physdev
);
936 static UINT
windrv_SetBoundsRect( PHYSDEV dev
, RECT
*rect
, UINT flags
)
938 /* do nothing, we use the dibdrv bounds tracking for our own purpose */
942 static INT
windrv_SetDIBitsToDevice( PHYSDEV dev
, INT x_dst
, INT y_dst
, DWORD cx
, DWORD cy
,
943 INT x_src
, INT y_src
, UINT startscan
, UINT lines
,
944 const void *bits
, BITMAPINFO
*src_info
, UINT coloruse
)
946 struct windrv_physdev
*physdev
= get_windrv_physdev( dev
);
949 lock_surface( physdev
);
950 dev
= GET_NEXT_PHYSDEV( dev
, pSetDIBitsToDevice
);
951 ret
= dev
->funcs
->pSetDIBitsToDevice( dev
, x_dst
, y_dst
, cx
, cy
,
952 x_src
, y_src
, startscan
, lines
, bits
, src_info
, coloruse
);
953 unlock_surface( physdev
);
957 static void windrv_SetDeviceClipping( PHYSDEV dev
, HRGN rgn
)
959 dev
= GET_NEXT_PHYSDEV( dev
, pSetDeviceClipping
);
960 dev
->funcs
->pSetDeviceClipping( dev
, rgn
);
961 /* also forward to the graphics driver for the OpenGL case */
962 if (dev
->funcs
== &dib_driver
)
964 dev
= GET_NEXT_PHYSDEV( dev
, pSetDeviceClipping
);
965 dev
->funcs
->pSetDeviceClipping( dev
, rgn
);
969 static COLORREF
windrv_SetPixel( PHYSDEV dev
, INT x
, INT y
, COLORREF color
)
971 struct windrv_physdev
*physdev
= get_windrv_physdev( dev
);
974 lock_surface( physdev
);
975 dev
= GET_NEXT_PHYSDEV( dev
, pSetPixel
);
976 ret
= dev
->funcs
->pSetPixel( dev
, x
, y
, color
);
977 unlock_surface( physdev
);
981 static BOOL
windrv_StretchBlt( PHYSDEV dst_dev
, struct bitblt_coords
*dst
,
982 PHYSDEV src_dev
, struct bitblt_coords
*src
, DWORD rop
)
984 struct windrv_physdev
*physdev
= get_windrv_physdev( dst_dev
);
987 lock_surface( physdev
);
988 dst_dev
= GET_NEXT_PHYSDEV( dst_dev
, pStretchBlt
);
989 ret
= dst_dev
->funcs
->pStretchBlt( dst_dev
, dst
, src_dev
, src
, rop
);
990 unlock_surface( physdev
);
994 static INT
windrv_StretchDIBits( PHYSDEV dev
, INT x_dst
, INT y_dst
, INT width_dst
, INT height_dst
,
995 INT x_src
, INT y_src
, INT width_src
, INT height_src
, const void *bits
,
996 BITMAPINFO
*src_info
, UINT coloruse
, DWORD rop
)
998 struct windrv_physdev
*physdev
= get_windrv_physdev( dev
);
1001 lock_surface( physdev
);
1002 dev
= GET_NEXT_PHYSDEV( dev
, pStretchDIBits
);
1003 ret
= dev
->funcs
->pStretchDIBits( dev
, x_dst
, y_dst
, width_dst
, height_dst
,
1004 x_src
, y_src
, width_src
, height_src
, bits
, src_info
, coloruse
, rop
);
1005 unlock_surface( physdev
);
1009 static struct opengl_funcs
*windrv_wine_get_wgl_driver( PHYSDEV dev
, UINT version
)
1011 dev
= GET_NEXT_PHYSDEV( dev
, wine_get_wgl_driver
);
1012 if (dev
->funcs
== &dib_driver
) dev
= GET_NEXT_PHYSDEV( dev
, wine_get_wgl_driver
);
1013 return dev
->funcs
->wine_get_wgl_driver( dev
, version
);
1016 static const struct gdi_dc_funcs window_driver
=
1018 NULL
, /* pAbortDoc */
1019 NULL
, /* pAbortPath */
1020 windrv_AlphaBlend
, /* pAlphaBlend */
1021 NULL
, /* pAngleArc */
1022 windrv_Arc
, /* pArc */
1023 windrv_ArcTo
, /* pArcTo */
1024 NULL
, /* pBeginPath */
1025 windrv_BlendImage
, /* pBlendImage */
1026 windrv_Chord
, /* pChord */
1027 NULL
, /* pCloseFigure */
1028 NULL
, /* pCreateCompatibleDC */
1029 windrv_CreateDC
, /* pCreateDC */
1030 windrv_DeleteDC
, /* pDeleteDC */
1031 NULL
, /* pDeleteObject */
1032 NULL
, /* pDeviceCapabilities */
1033 windrv_Ellipse
, /* pEllipse */
1035 NULL
, /* pEndPage */
1036 NULL
, /* pEndPath */
1037 NULL
, /* pEnumFonts */
1038 NULL
, /* pEnumICMProfiles */
1039 NULL
, /* pExcludeClipRect */
1040 NULL
, /* pExtDeviceMode */
1041 NULL
, /* pExtEscape */
1042 windrv_ExtFloodFill
, /* pExtFloodFill */
1043 NULL
, /* pExtSelectClipRgn */
1044 windrv_ExtTextOut
, /* pExtTextOut */
1045 NULL
, /* pFillPath */
1046 NULL
, /* pFillRgn */
1047 NULL
, /* pFlattenPath */
1048 NULL
, /* pFontIsLinked */
1049 NULL
, /* pFrameRgn */
1050 NULL
, /* pGdiComment */
1051 NULL
, /* pGetBoundsRect */
1052 NULL
, /* pGetCharABCWidths */
1053 NULL
, /* pGetCharABCWidthsI */
1054 NULL
, /* pGetCharWidth */
1055 NULL
, /* pGetDeviceCaps */
1056 NULL
, /* pGetDeviceGammaRamp */
1057 NULL
, /* pGetFontData */
1058 NULL
, /* pGetFontRealizationInfo */
1059 NULL
, /* pGetFontUnicodeRanges */
1060 NULL
, /* pGetGlyphIndices */
1061 NULL
, /* pGetGlyphOutline */
1062 NULL
, /* pGetICMProfile */
1063 windrv_GetImage
, /* pGetImage */
1064 NULL
, /* pGetKerningPairs */
1065 NULL
, /* pGetNearestColor */
1066 NULL
, /* pGetOutlineTextMetrics */
1067 windrv_GetPixel
, /* pGetPixel */
1068 NULL
, /* pGetSystemPaletteEntries */
1069 NULL
, /* pGetTextCharsetInfo */
1070 NULL
, /* pGetTextExtentExPoint */
1071 NULL
, /* pGetTextExtentExPointI */
1072 NULL
, /* pGetTextFace */
1073 NULL
, /* pGetTextMetrics */
1074 windrv_GradientFill
, /* pGradientFill */
1075 NULL
, /* pIntersectClipRect */
1076 NULL
, /* pInvertRgn */
1077 windrv_LineTo
, /* pLineTo */
1078 NULL
, /* pModifyWorldTransform */
1080 NULL
, /* pOffsetClipRgn */
1081 NULL
, /* pOffsetViewportOrg */
1082 NULL
, /* pOffsetWindowOrg */
1083 windrv_PaintRgn
, /* pPaintRgn */
1084 windrv_PatBlt
, /* pPatBlt */
1085 windrv_Pie
, /* pPie */
1086 NULL
, /* pPolyBezier */
1087 NULL
, /* pPolyBezierTo */
1088 NULL
, /* pPolyDraw */
1089 windrv_PolyPolygon
, /* pPolyPolygon */
1090 windrv_PolyPolyline
, /* pPolyPolyline */
1091 windrv_Polygon
, /* pPolygon */
1092 windrv_Polyline
, /* pPolyline */
1093 NULL
, /* pPolylineTo */
1094 windrv_PutImage
, /* pPutImage */
1095 NULL
, /* pRealizeDefaultPalette */
1096 NULL
, /* pRealizePalette */
1097 windrv_Rectangle
, /* pRectangle */
1098 NULL
, /* pResetDC */
1099 NULL
, /* pRestoreDC */
1100 windrv_RoundRect
, /* pRoundRect */
1102 NULL
, /* pScaleViewportExt */
1103 NULL
, /* pScaleWindowExt */
1104 NULL
, /* pSelectBitmap */
1105 NULL
, /* pSelectBrush */
1106 NULL
, /* pSelectClipPath */
1107 NULL
, /* pSelectFont */
1108 NULL
, /* pSelectPalette */
1109 NULL
, /* pSelectPen */
1110 NULL
, /* pSetArcDirection */
1111 NULL
, /* pSetBkColor */
1112 NULL
, /* pSetBkMode */
1113 windrv_SetBoundsRect
, /* pSetBoundsRect */
1114 NULL
, /* pSetDCBrushColor */
1115 NULL
, /* pSetDCPenColor */
1116 windrv_SetDIBitsToDevice
, /* pSetDIBitsToDevice */
1117 windrv_SetDeviceClipping
, /* pSetDeviceClipping */
1118 NULL
, /* pSetDeviceGammaRamp */
1119 NULL
, /* pSetLayout */
1120 NULL
, /* pSetMapMode */
1121 NULL
, /* pSetMapperFlags */
1122 windrv_SetPixel
, /* pSetPixel */
1123 NULL
, /* pSetPolyFillMode */
1124 NULL
, /* pSetROP2 */
1125 NULL
, /* pSetRelAbs */
1126 NULL
, /* pSetStretchBltMode */
1127 NULL
, /* pSetTextAlign */
1128 NULL
, /* pSetTextCharacterExtra */
1129 NULL
, /* pSetTextColor */
1130 NULL
, /* pSetTextJustification */
1131 NULL
, /* pSetViewportExt */
1132 NULL
, /* pSetViewportOrg */
1133 NULL
, /* pSetWindowExt */
1134 NULL
, /* pSetWindowOrg */
1135 NULL
, /* pSetWorldTransform */
1136 NULL
, /* pStartDoc */
1137 NULL
, /* pStartPage */
1138 windrv_StretchBlt
, /* pStretchBlt */
1139 windrv_StretchDIBits
, /* pStretchDIBits */
1140 NULL
, /* pStrokeAndFillPath */
1141 NULL
, /* pStrokePath */
1142 NULL
, /* pUnrealizePalette */
1143 NULL
, /* pWidenPath */
1144 windrv_wine_get_wgl_driver
, /* wine_get_wgl_driver */
1145 NULL
, /* wine_get_vulkan_driver */
1146 GDI_PRIORITY_DIB_DRV
+ 10 /* priority */