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 init_dib_info( dib
, &info
->bmiHeader
, get_dib_stride( info
->bmiHeader
.biWidth
, info
->bmiHeader
.biBitCount
),
158 (const DWORD
*)info
->bmiColors
, info
->bmiColors
, bits
);
161 BOOL
init_dib_info_from_bitmapobj(dib_info
*dib
, BITMAPOBJ
*bmp
)
163 if (!is_bitmapobj_dib( bmp
))
167 get_ddb_bitmapinfo( bmp
, &info
);
168 if (!bmp
->dib
.dsBm
.bmBits
)
170 int width_bytes
= get_dib_stride( bmp
->dib
.dsBm
.bmWidth
, bmp
->dib
.dsBm
.bmBitsPixel
);
171 bmp
->dib
.dsBm
.bmBits
= HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY
,
172 bmp
->dib
.dsBm
.bmHeight
* width_bytes
);
173 if (!bmp
->dib
.dsBm
.bmBits
) return FALSE
;
175 init_dib_info_from_bitmapinfo( dib
, &info
, bmp
->dib
.dsBm
.bmBits
);
177 else init_dib_info( dib
, &bmp
->dib
.dsBmih
, bmp
->dib
.dsBm
.bmWidthBytes
,
178 bmp
->dib
.dsBitfields
, bmp
->color_table
, bmp
->dib
.dsBm
.bmBits
);
182 static void clear_dib_info(dib_info
*dib
)
184 dib
->bits
.ptr
= NULL
;
185 dib
->bits
.free
= NULL
;
186 dib
->bits
.param
= NULL
;
189 /**********************************************************************
192 * Free the resources associated with a dib and optionally the bits
194 void free_dib_info(dib_info
*dib
)
196 if (dib
->bits
.free
) dib
->bits
.free( &dib
->bits
);
197 clear_dib_info( dib
);
200 void copy_dib_color_info(dib_info
*dst
, const dib_info
*src
)
202 dst
->bit_count
= src
->bit_count
;
203 dst
->red_mask
= src
->red_mask
;
204 dst
->green_mask
= src
->green_mask
;
205 dst
->blue_mask
= src
->blue_mask
;
206 dst
->red_len
= src
->red_len
;
207 dst
->green_len
= src
->green_len
;
208 dst
->blue_len
= src
->blue_len
;
209 dst
->red_shift
= src
->red_shift
;
210 dst
->green_shift
= src
->green_shift
;
211 dst
->blue_shift
= src
->blue_shift
;
212 dst
->funcs
= src
->funcs
;
213 dst
->color_table_size
= src
->color_table_size
;
214 dst
->color_table
= src
->color_table
;
217 DWORD
convert_bitmapinfo( const BITMAPINFO
*src_info
, void *src_bits
, struct bitblt_coords
*src
,
218 const BITMAPINFO
*dst_info
, void *dst_bits
)
220 dib_info src_dib
, dst_dib
;
223 init_dib_info_from_bitmapinfo( &src_dib
, src_info
, src_bits
);
224 init_dib_info_from_bitmapinfo( &dst_dib
, dst_info
, dst_bits
);
228 dst_dib
.funcs
->convert_to( &dst_dib
, &src_dib
, &src
->visrect
, FALSE
);
233 WARN( "invalid bits pointer %p\n", src_bits
);
238 if(!ret
) return ERROR_BAD_FORMAT
;
240 /* update coordinates, the destination rectangle is always stored at 0,0 */
241 src
->x
-= src
->visrect
.left
;
242 src
->y
-= src
->visrect
.top
;
243 offset_rect( &src
->visrect
, -src
->visrect
.left
, -src
->visrect
.top
);
244 return ERROR_SUCCESS
;
247 int clip_rect_to_dib( const dib_info
*dib
, RECT
*rc
)
251 rect
.left
= max( 0, -dib
->rect
.left
);
252 rect
.top
= max( 0, -dib
->rect
.top
);
253 rect
.right
= min( dib
->rect
.right
, dib
->width
) - dib
->rect
.left
;
254 rect
.bottom
= min( dib
->rect
.bottom
, dib
->height
) - dib
->rect
.top
;
255 if (is_rect_empty( &rect
)) return 0;
256 return 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 rect
.left
= max( 0, -dib
->rect
.left
);
268 rect
.top
= max( 0, -dib
->rect
.top
);
269 rect
.right
= min( dib
->rect
.right
, dib
->width
) - dib
->rect
.left
;
270 rect
.bottom
= min( dib
->rect
.bottom
, dib
->height
) - dib
->rect
.top
;
271 if (is_rect_empty( &rect
)) return 0;
272 if (rc
&& !intersect_rect( &rect
, &rect
, rc
)) return 0;
277 clip_rects
->count
= 1;
281 if (!(region
= get_wine_region( clip
))) return 0;
283 for (i
= region_find_pt( region
, rect
.left
, rect
.top
, NULL
); i
< region
->numRects
; i
++)
285 if (region
->rects
[i
].top
>= rect
.bottom
) break;
286 if (!intersect_rect( out
, &rect
, ®ion
->rects
[i
] )) continue;
288 if (out
== &clip_rects
->buffer
[sizeof(clip_rects
->buffer
) / sizeof(RECT
)])
290 clip_rects
->rects
= HeapAlloc( GetProcessHeap(), 0, region
->numRects
* sizeof(RECT
) );
291 if (!clip_rects
->rects
) return 0;
292 memcpy( clip_rects
->rects
, clip_rects
->buffer
, (out
- clip_rects
->buffer
) * sizeof(RECT
) );
293 out
= clip_rects
->rects
+ (out
- clip_rects
->buffer
);
296 release_wine_region( clip
);
297 clip_rects
->count
= out
- clip_rects
->rects
;
298 return clip_rects
->count
;
301 void add_clipped_bounds( dibdrv_physdev
*dev
, const RECT
*rect
, HRGN clip
)
303 const WINEREGION
*region
;
306 if (!dev
->bounds
) return;
309 if (!(region
= get_wine_region( clip
))) return;
310 if (!rect
) rc
= region
->extents
;
311 else intersect_rect( &rc
, rect
, ®ion
->extents
);
312 release_wine_region( clip
);
316 if (is_rect_empty( &rc
)) return;
317 offset_rect( &rc
, dev
->dib
.rect
.left
, dev
->dib
.rect
.top
);
318 add_bounds_rect( dev
->bounds
, &rc
);
321 /**********************************************************************
324 static BOOL
dibdrv_CreateDC( PHYSDEV
*dev
, LPCWSTR driver
, LPCWSTR device
,
325 LPCWSTR output
, const DEVMODEW
*data
)
327 dibdrv_physdev
*pdev
= HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(*pdev
) );
329 if (!pdev
) return FALSE
;
330 clear_dib_info(&pdev
->dib
);
331 clear_dib_info(&pdev
->brush
.dib
);
332 clear_dib_info(&pdev
->pen_brush
.dib
);
333 push_dc_driver( dev
, &pdev
->dev
, &dib_driver
);
337 /***********************************************************************
340 static BOOL
dibdrv_DeleteDC( PHYSDEV dev
)
342 dibdrv_physdev
*pdev
= get_dibdrv_pdev(dev
);
343 TRACE("(%p)\n", dev
);
344 free_pattern_brush( &pdev
->brush
);
345 free_pattern_brush( &pdev
->pen_brush
);
346 release_cached_font( pdev
->font
);
347 HeapFree( GetProcessHeap(), 0, pdev
);
351 /***********************************************************************
352 * dibdrv_SelectBitmap
354 static HBITMAP
dibdrv_SelectBitmap( PHYSDEV dev
, HBITMAP bitmap
)
356 dibdrv_physdev
*pdev
= get_dibdrv_pdev(dev
);
357 BITMAPOBJ
*bmp
= GDI_GetObjPtr( bitmap
, OBJ_BITMAP
);
360 TRACE("(%p, %p)\n", dev
, bitmap
);
364 if (!init_dib_info_from_bitmapobj(&dib
, bmp
))
366 GDI_ReleaseObj( bitmap
);
370 GDI_ReleaseObj( bitmap
);
375 /***********************************************************************
376 * dibdrv_SetDeviceClipping
378 static void dibdrv_SetDeviceClipping( PHYSDEV dev
, HRGN rgn
)
380 dibdrv_physdev
*pdev
= get_dibdrv_pdev(dev
);
381 TRACE("(%p, %p)\n", dev
, rgn
);
386 /***********************************************************************
387 * dibdrv_SetBoundsRect
389 static UINT
dibdrv_SetBoundsRect( PHYSDEV dev
, RECT
*rect
, UINT flags
)
391 dibdrv_physdev
*pdev
= get_dibdrv_pdev( dev
);
393 if (flags
& DCB_DISABLE
) pdev
->bounds
= NULL
;
394 else if (flags
& DCB_ENABLE
) pdev
->bounds
= rect
;
395 return DCB_RESET
; /* we don't have device-specific bounds */
398 const struct gdi_dc_funcs dib_driver
=
400 NULL
, /* pAbortDoc */
401 NULL
, /* pAbortPath */
402 dibdrv_AlphaBlend
, /* pAlphaBlend */
403 NULL
, /* pAngleArc */
404 dibdrv_Arc
, /* pArc */
405 dibdrv_ArcTo
, /* pArcTo */
406 NULL
, /* pBeginPath */
407 dibdrv_BlendImage
, /* pBlendImage */
408 dibdrv_Chord
, /* pChord */
409 NULL
, /* pCloseFigure */
410 NULL
, /* pCreateCompatibleDC */
411 dibdrv_CreateDC
, /* pCreateDC */
412 dibdrv_DeleteDC
, /* pDeleteDC */
413 NULL
, /* pDeleteObject */
414 NULL
, /* pDeviceCapabilities */
415 dibdrv_Ellipse
, /* pEllipse */
419 NULL
, /* pEnumFonts */
420 NULL
, /* pEnumICMProfiles */
421 NULL
, /* pExcludeClipRect */
422 NULL
, /* pExtDeviceMode */
423 NULL
, /* pExtEscape */
424 dibdrv_ExtFloodFill
, /* pExtFloodFill */
425 NULL
, /* pExtSelectClipRgn */
426 dibdrv_ExtTextOut
, /* pExtTextOut */
427 dibdrv_FillPath
, /* pFillPath */
429 NULL
, /* pFlattenPath */
430 NULL
, /* pFontIsLinked */
431 NULL
, /* pFrameRgn */
432 NULL
, /* pGdiComment */
433 NULL
, /* pGetBoundsRect */
434 NULL
, /* pGetCharABCWidths */
435 NULL
, /* pGetCharABCWidthsI */
436 NULL
, /* pGetCharWidth */
437 NULL
, /* pGetDeviceCaps */
438 NULL
, /* pGetDeviceGammaRamp */
439 NULL
, /* pGetFontData */
440 NULL
, /* pGetFontRealizationInfo */
441 NULL
, /* pGetFontUnicodeRanges */
442 NULL
, /* pGetGlyphIndices */
443 NULL
, /* pGetGlyphOutline */
444 NULL
, /* pGetICMProfile */
445 dibdrv_GetImage
, /* pGetImage */
446 NULL
, /* pGetKerningPairs */
447 dibdrv_GetNearestColor
, /* pGetNearestColor */
448 NULL
, /* pGetOutlineTextMetrics */
449 dibdrv_GetPixel
, /* pGetPixel */
450 NULL
, /* pGetSystemPaletteEntries */
451 NULL
, /* pGetTextCharsetInfo */
452 NULL
, /* pGetTextExtentExPoint */
453 NULL
, /* pGetTextExtentExPointI */
454 NULL
, /* pGetTextFace */
455 NULL
, /* pGetTextMetrics */
456 dibdrv_GradientFill
, /* pGradientFill */
457 NULL
, /* pIntersectClipRect */
458 NULL
, /* pInvertRgn */
459 dibdrv_LineTo
, /* pLineTo */
460 NULL
, /* pModifyWorldTransform */
462 NULL
, /* pOffsetClipRgn */
463 NULL
, /* pOffsetViewportOrg */
464 NULL
, /* pOffsetWindowOrg */
465 dibdrv_PaintRgn
, /* pPaintRgn */
466 dibdrv_PatBlt
, /* pPatBlt */
467 dibdrv_Pie
, /* pPie */
468 NULL
, /* pPolyBezier */
469 NULL
, /* pPolyBezierTo */
470 NULL
, /* pPolyDraw */
471 dibdrv_PolyPolygon
, /* pPolyPolygon */
472 dibdrv_PolyPolyline
, /* pPolyPolyline */
473 dibdrv_Polygon
, /* pPolygon */
474 dibdrv_Polyline
, /* pPolyline */
475 NULL
, /* pPolylineTo */
476 dibdrv_PutImage
, /* pPutImage */
477 NULL
, /* pRealizeDefaultPalette */
478 NULL
, /* pRealizePalette */
479 dibdrv_Rectangle
, /* pRectangle */
481 NULL
, /* pRestoreDC */
482 dibdrv_RoundRect
, /* pRoundRect */
484 NULL
, /* pScaleViewportExt */
485 NULL
, /* pScaleWindowExt */
486 dibdrv_SelectBitmap
, /* pSelectBitmap */
487 dibdrv_SelectBrush
, /* pSelectBrush */
488 NULL
, /* pSelectClipPath */
489 dibdrv_SelectFont
, /* pSelectFont */
490 NULL
, /* pSelectPalette */
491 dibdrv_SelectPen
, /* pSelectPen */
492 NULL
, /* pSetArcDirection */
493 NULL
, /* pSetBkColor */
494 NULL
, /* pSetBkMode */
495 dibdrv_SetBoundsRect
, /* pSetBoundsRect */
496 dibdrv_SetDCBrushColor
, /* pSetDCBrushColor */
497 dibdrv_SetDCPenColor
, /* pSetDCPenColor */
498 NULL
, /* pSetDIBitsToDevice */
499 dibdrv_SetDeviceClipping
, /* pSetDeviceClipping */
500 NULL
, /* pSetDeviceGammaRamp */
501 NULL
, /* pSetLayout */
502 NULL
, /* pSetMapMode */
503 NULL
, /* pSetMapperFlags */
504 dibdrv_SetPixel
, /* pSetPixel */
505 NULL
, /* pSetPolyFillMode */
507 NULL
, /* pSetRelAbs */
508 NULL
, /* pSetStretchBltMode */
509 NULL
, /* pSetTextAlign */
510 NULL
, /* pSetTextCharacterExtra */
511 NULL
, /* pSetTextColor */
512 NULL
, /* pSetTextJustification */
513 NULL
, /* pSetViewportExt */
514 NULL
, /* pSetViewportOrg */
515 NULL
, /* pSetWindowExt */
516 NULL
, /* pSetWindowOrg */
517 NULL
, /* pSetWorldTransform */
518 NULL
, /* pStartDoc */
519 NULL
, /* pStartPage */
520 dibdrv_StretchBlt
, /* pStretchBlt */
521 NULL
, /* pStretchDIBits */
522 dibdrv_StrokeAndFillPath
, /* pStrokeAndFillPath */
523 dibdrv_StrokePath
, /* pStrokePath */
524 NULL
, /* pUnrealizePalette */
525 NULL
, /* pWidenPath */
526 dibdrv_wine_get_wgl_driver
, /* wine_get_wgl_driver */
527 GDI_PRIORITY_DIB_DRV
/* priority */
531 /***********************************************************************
532 * Driver for window surfaces.
534 * It uses the DIB engine but needs extra locking since multiple DCs
535 * can paint to the same window.
538 #define FLUSH_PERIOD 50 /* time in ms since drawing started for forcing a surface flush */
540 struct windrv_physdev
542 struct gdi_physdev dev
;
543 struct dibdrv_physdev
*dibdrv
;
544 struct window_surface
*surface
;
548 static const struct gdi_dc_funcs window_driver
;
550 static inline struct windrv_physdev
*get_windrv_physdev( PHYSDEV dev
)
552 return (struct windrv_physdev
*)dev
;
555 static inline void lock_surface( struct windrv_physdev
*dev
)
558 dev
->surface
->funcs
->lock( dev
->surface
);
559 if (is_rect_empty( dev
->dibdrv
->bounds
)) dev
->start_ticks
= GetTickCount();
562 static inline void unlock_surface( struct windrv_physdev
*dev
)
564 dev
->surface
->funcs
->unlock( dev
->surface
);
565 if (GetTickCount() - dev
->start_ticks
> FLUSH_PERIOD
) dev
->surface
->funcs
->flush( dev
->surface
);
568 static void unlock_bits_surface( struct gdi_image_bits
*bits
)
570 struct window_surface
*surface
= bits
->param
;
571 surface
->funcs
->unlock( surface
);
574 void dibdrv_set_window_surface( DC
*dc
, struct window_surface
*surface
)
576 char buffer
[FIELD_OFFSET( BITMAPINFO
, bmiColors
[256] )];
577 BITMAPINFO
*info
= (BITMAPINFO
*)buffer
;
581 struct windrv_physdev
*physdev
;
582 struct dibdrv_physdev
*dibdrv
;
584 TRACE( "%p %p\n", dc
->hSelf
, surface
);
586 windev
= pop_dc_driver( dc
, &window_driver
);
590 if (windev
) push_dc_driver( &dc
->physDev
, windev
, windev
->funcs
);
593 if (!window_driver
.pCreateDC( &dc
->physDev
, NULL
, NULL
, NULL
, NULL
)) return;
594 windev
= find_dc_driver( dc
, &window_driver
);
597 physdev
= get_windrv_physdev( windev
);
598 window_surface_add_ref( surface
);
599 if (physdev
->surface
) window_surface_release( physdev
->surface
);
600 physdev
->surface
= surface
;
602 dibdrv
= physdev
->dibdrv
;
603 bits
= surface
->funcs
->get_info( surface
, info
);
604 init_dib_info_from_bitmapinfo( &dibdrv
->dib
, info
, bits
);
605 /* clip the device rect to the surface */
606 rect
= surface
->rect
;
607 offset_rect( &rect
, dc
->device_rect
.left
, dc
->device_rect
.top
);
608 intersect_rect( &dc
->device_rect
, &dc
->device_rect
, &rect
);
609 dibdrv
->dib
.rect
= dc
->vis_rect
;
610 offset_rect( &dibdrv
->dib
.rect
, -rect
.left
, -rect
.top
);
611 dibdrv
->bounds
= surface
->funcs
->get_bounds( surface
);
616 dib_driver
.pDeleteDC( pop_dc_driver( dc
, &dib_driver
));
617 windev
->funcs
->pDeleteDC( windev
);
622 static BOOL
windrv_AlphaBlend( PHYSDEV dst_dev
, struct bitblt_coords
*dst
,
623 PHYSDEV src_dev
, struct bitblt_coords
*src
, BLENDFUNCTION func
)
625 struct windrv_physdev
*physdev
= get_windrv_physdev( dst_dev
);
628 lock_surface( physdev
);
629 dst_dev
= GET_NEXT_PHYSDEV( dst_dev
, pAlphaBlend
);
630 ret
= dst_dev
->funcs
->pAlphaBlend( dst_dev
, dst
, src_dev
, src
, func
);
631 unlock_surface( physdev
);
635 static BOOL
windrv_Arc( PHYSDEV dev
, INT left
, INT top
, INT right
, INT bottom
,
636 INT xstart
, INT ystart
, INT xend
, INT yend
)
638 struct windrv_physdev
*physdev
= get_windrv_physdev( dev
);
641 lock_surface( physdev
);
642 dev
= GET_NEXT_PHYSDEV( dev
, pArc
);
643 ret
= dev
->funcs
->pArc( dev
, left
, top
, right
, bottom
, xstart
, ystart
, xend
, yend
);
644 unlock_surface( physdev
);
648 static BOOL
windrv_ArcTo( PHYSDEV dev
, INT left
, INT top
, INT right
, INT bottom
,
649 INT xstart
, INT ystart
, INT xend
, INT yend
)
651 struct windrv_physdev
*physdev
= get_windrv_physdev( dev
);
654 lock_surface( physdev
);
655 dev
= GET_NEXT_PHYSDEV( dev
, pArc
);
656 ret
= dev
->funcs
->pArcTo( dev
, left
, top
, right
, bottom
, xstart
, ystart
, xend
, yend
);
657 unlock_surface( physdev
);
661 static DWORD
windrv_BlendImage( PHYSDEV dev
, BITMAPINFO
*info
, const struct gdi_image_bits
*bits
,
662 struct bitblt_coords
*src
, struct bitblt_coords
*dst
, BLENDFUNCTION blend
)
664 struct windrv_physdev
*physdev
= get_windrv_physdev( dev
);
667 lock_surface( physdev
);
668 dev
= GET_NEXT_PHYSDEV( dev
, pBlendImage
);
669 ret
= dev
->funcs
->pBlendImage( dev
, info
, bits
, src
, dst
, blend
);
670 unlock_surface( physdev
);
674 static BOOL
windrv_Chord( PHYSDEV dev
, INT left
, INT top
, INT right
, INT bottom
,
675 INT xstart
, INT ystart
, INT xend
, INT yend
)
677 struct windrv_physdev
*physdev
= get_windrv_physdev( dev
);
680 lock_surface( physdev
);
681 dev
= GET_NEXT_PHYSDEV( dev
, pChord
);
682 ret
= dev
->funcs
->pChord( dev
, left
, top
, right
, bottom
, xstart
, ystart
, xend
, yend
);
683 unlock_surface( physdev
);
687 static BOOL
windrv_CreateDC( PHYSDEV
*dev
, LPCWSTR driver
, LPCWSTR device
,
688 LPCWSTR output
, const DEVMODEW
*devmode
)
690 struct windrv_physdev
*physdev
= HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(*physdev
) );
692 if (!physdev
) return FALSE
;
694 if (!dib_driver
.pCreateDC( dev
, NULL
, NULL
, NULL
, NULL
))
696 HeapFree( GetProcessHeap(), 0, physdev
);
699 physdev
->dibdrv
= get_dibdrv_pdev( *dev
);
700 push_dc_driver( dev
, &physdev
->dev
, &window_driver
);
704 static BOOL
windrv_DeleteDC( PHYSDEV dev
)
706 struct windrv_physdev
*physdev
= get_windrv_physdev( dev
);
708 window_surface_release( physdev
->surface
);
709 HeapFree( GetProcessHeap(), 0, physdev
);
713 static BOOL
windrv_Ellipse( PHYSDEV dev
, INT left
, INT top
, INT right
, INT bottom
)
715 struct windrv_physdev
*physdev
= get_windrv_physdev( dev
);
718 lock_surface( physdev
);
719 dev
= GET_NEXT_PHYSDEV( dev
, pEllipse
);
720 ret
= dev
->funcs
->pEllipse( dev
, left
, top
, right
, bottom
);
721 unlock_surface( physdev
);
725 static BOOL
windrv_ExtFloodFill( PHYSDEV dev
, INT x
, INT y
, COLORREF color
, UINT type
)
727 struct windrv_physdev
*physdev
= get_windrv_physdev( dev
);
730 lock_surface( physdev
);
731 dev
= GET_NEXT_PHYSDEV( dev
, pExtFloodFill
);
732 ret
= dev
->funcs
->pExtFloodFill( dev
, x
, y
, color
, type
);
733 unlock_surface( physdev
);
737 static BOOL
windrv_ExtTextOut( PHYSDEV dev
, INT x
, INT y
, UINT flags
, const RECT
*rect
,
738 LPCWSTR str
, UINT count
, const INT
*dx
)
740 struct windrv_physdev
*physdev
= get_windrv_physdev( dev
);
743 lock_surface( physdev
);
744 dev
= GET_NEXT_PHYSDEV( dev
, pExtTextOut
);
745 ret
= dev
->funcs
->pExtTextOut( dev
, x
, y
, flags
, rect
, str
, count
, dx
);
746 unlock_surface( physdev
);
750 static DWORD
windrv_GetImage( PHYSDEV dev
, BITMAPINFO
*info
,
751 struct gdi_image_bits
*bits
, struct bitblt_coords
*src
)
753 struct windrv_physdev
*physdev
= get_windrv_physdev( dev
);
756 lock_surface( physdev
);
757 dev
= GET_NEXT_PHYSDEV( dev
, pGetImage
);
758 ret
= dev
->funcs
->pGetImage( dev
, info
, bits
, src
);
760 /* don't return alpha if original surface doesn't support it */
761 if (info
->bmiHeader
.biBitCount
== 32 &&
762 info
->bmiHeader
.biCompression
== BI_RGB
&&
763 physdev
->dibdrv
->dib
.compression
== BI_BITFIELDS
)
765 DWORD
*colors
= (DWORD
*)info
->bmiColors
;
766 colors
[0] = 0xff0000;
767 colors
[1] = 0x00ff00;
768 colors
[2] = 0x0000ff;
769 info
->bmiHeader
.biCompression
= BI_BITFIELDS
;
774 /* use the freeing callback to unlock the surface */
775 assert( !bits
->free
);
776 bits
->free
= unlock_bits_surface
;
777 bits
->param
= physdev
->surface
;
779 else unlock_surface( physdev
);
783 static COLORREF
windrv_GetPixel( PHYSDEV dev
, INT x
, INT y
)
785 struct windrv_physdev
*physdev
= get_windrv_physdev( dev
);
788 lock_surface( physdev
);
789 dev
= GET_NEXT_PHYSDEV( dev
, pGetPixel
);
790 ret
= dev
->funcs
->pGetPixel( dev
, x
, y
);
791 unlock_surface( physdev
);
795 static BOOL
windrv_GradientFill( PHYSDEV dev
, TRIVERTEX
*vert_array
, ULONG nvert
,
796 void * grad_array
, ULONG ngrad
, ULONG mode
)
798 struct windrv_physdev
*physdev
= get_windrv_physdev( dev
);
801 lock_surface( physdev
);
802 dev
= GET_NEXT_PHYSDEV( dev
, pGradientFill
);
803 ret
= dev
->funcs
->pGradientFill( dev
, vert_array
, nvert
, grad_array
, ngrad
, mode
);
804 unlock_surface( physdev
);
808 static BOOL
windrv_LineTo( PHYSDEV dev
, INT x
, INT y
)
810 struct windrv_physdev
*physdev
= get_windrv_physdev( dev
);
813 lock_surface( physdev
);
814 dev
= GET_NEXT_PHYSDEV( dev
, pLineTo
);
815 ret
= dev
->funcs
->pLineTo( dev
, x
, y
);
816 unlock_surface( physdev
);
820 static BOOL
windrv_PaintRgn( PHYSDEV dev
, HRGN rgn
)
822 struct windrv_physdev
*physdev
= get_windrv_physdev( dev
);
825 lock_surface( physdev
);
826 dev
= GET_NEXT_PHYSDEV( dev
, pPaintRgn
);
827 ret
= dev
->funcs
->pPaintRgn( dev
, rgn
);
828 unlock_surface( physdev
);
832 static BOOL
windrv_PatBlt( PHYSDEV dev
, struct bitblt_coords
*dst
, DWORD rop
)
834 struct windrv_physdev
*physdev
= get_windrv_physdev( dev
);
837 lock_surface( physdev
);
838 dev
= GET_NEXT_PHYSDEV( dev
, pPatBlt
);
839 ret
= dev
->funcs
->pPatBlt( dev
, dst
, rop
);
840 unlock_surface( physdev
);
844 static BOOL
windrv_Pie( PHYSDEV dev
, INT left
, INT top
, INT right
, INT bottom
,
845 INT xstart
, INT ystart
, INT xend
, INT yend
)
847 struct windrv_physdev
*physdev
= get_windrv_physdev( dev
);
850 lock_surface( physdev
);
851 dev
= GET_NEXT_PHYSDEV( dev
, pPie
);
852 ret
= dev
->funcs
->pPie( dev
, left
, top
, right
, bottom
, xstart
, ystart
, xend
, yend
);
853 unlock_surface( physdev
);
857 static BOOL
windrv_PolyPolygon( PHYSDEV dev
, const POINT
*points
, const INT
*counts
, UINT polygons
)
859 struct windrv_physdev
*physdev
= get_windrv_physdev( dev
);
862 lock_surface( physdev
);
863 dev
= GET_NEXT_PHYSDEV( dev
, pPolyPolygon
);
864 ret
= dev
->funcs
->pPolyPolygon( dev
, points
, counts
, polygons
);
865 unlock_surface( physdev
);
869 static BOOL
windrv_PolyPolyline( PHYSDEV dev
, const POINT
*points
, const DWORD
*counts
, DWORD lines
)
871 struct windrv_physdev
*physdev
= get_windrv_physdev( dev
);
874 lock_surface( physdev
);
875 dev
= GET_NEXT_PHYSDEV( dev
, pPolyPolyline
);
876 ret
= dev
->funcs
->pPolyPolyline( dev
, points
, counts
, lines
);
877 unlock_surface( physdev
);
881 static BOOL
windrv_Polygon( PHYSDEV dev
, const POINT
*points
, INT count
)
883 struct windrv_physdev
*physdev
= get_windrv_physdev( dev
);
886 lock_surface( physdev
);
887 dev
= GET_NEXT_PHYSDEV( dev
, pPolygon
);
888 ret
= dev
->funcs
->pPolygon( dev
, points
, count
);
889 unlock_surface( physdev
);
893 static BOOL
windrv_Polyline( PHYSDEV dev
, const POINT
*points
, INT count
)
895 struct windrv_physdev
*physdev
= get_windrv_physdev( dev
);
898 lock_surface( physdev
);
899 dev
= GET_NEXT_PHYSDEV( dev
, pPolyline
);
900 ret
= dev
->funcs
->pPolyline( dev
, points
, count
);
901 unlock_surface( physdev
);
905 static DWORD
windrv_PutImage( PHYSDEV dev
, HRGN clip
, BITMAPINFO
*info
,
906 const struct gdi_image_bits
*bits
, struct bitblt_coords
*src
,
907 struct bitblt_coords
*dst
, DWORD rop
)
909 struct windrv_physdev
*physdev
= get_windrv_physdev( dev
);
912 lock_surface( physdev
);
913 dev
= GET_NEXT_PHYSDEV( dev
, pPutImage
);
914 ret
= dev
->funcs
->pPutImage( dev
, clip
, info
, bits
, src
, dst
, rop
);
915 unlock_surface( physdev
);
919 static BOOL
windrv_Rectangle( PHYSDEV dev
, INT left
, INT top
, INT right
, INT bottom
)
921 struct windrv_physdev
*physdev
= get_windrv_physdev( dev
);
924 lock_surface( physdev
);
925 dev
= GET_NEXT_PHYSDEV( dev
, pRectangle
);
926 ret
= dev
->funcs
->pRectangle( dev
, left
, top
, right
, bottom
);
927 unlock_surface( physdev
);
931 static BOOL
windrv_RoundRect( PHYSDEV dev
, INT left
, INT top
, INT right
, INT bottom
,
932 INT ell_width
, INT ell_height
)
934 struct windrv_physdev
*physdev
= get_windrv_physdev( dev
);
937 lock_surface( physdev
);
938 dev
= GET_NEXT_PHYSDEV( dev
, pRoundRect
);
939 ret
= dev
->funcs
->pRoundRect( dev
, left
, top
, right
, bottom
, ell_width
, ell_height
);
940 unlock_surface( physdev
);
944 static UINT
windrv_SetBoundsRect( PHYSDEV dev
, RECT
*rect
, UINT flags
)
946 /* do nothing, we use the dibdrv bounds tracking for our own purpose */
950 static INT
windrv_SetDIBitsToDevice( PHYSDEV dev
, INT x_dst
, INT y_dst
, DWORD cx
, DWORD cy
,
951 INT x_src
, INT y_src
, UINT startscan
, UINT lines
,
952 const void *bits
, BITMAPINFO
*src_info
, UINT coloruse
)
954 struct windrv_physdev
*physdev
= get_windrv_physdev( dev
);
957 lock_surface( physdev
);
958 dev
= GET_NEXT_PHYSDEV( dev
, pSetDIBitsToDevice
);
959 ret
= dev
->funcs
->pSetDIBitsToDevice( dev
, x_dst
, y_dst
, cx
, cy
,
960 x_src
, y_src
, startscan
, lines
, bits
, src_info
, coloruse
);
961 unlock_surface( physdev
);
965 static void windrv_SetDeviceClipping( PHYSDEV dev
, HRGN rgn
)
967 dev
= GET_NEXT_PHYSDEV( dev
, pSetDeviceClipping
);
968 dev
->funcs
->pSetDeviceClipping( dev
, rgn
);
969 /* also forward to the graphics driver for the OpenGL case */
970 if (dev
->funcs
== &dib_driver
)
972 dev
= GET_NEXT_PHYSDEV( dev
, pSetDeviceClipping
);
973 dev
->funcs
->pSetDeviceClipping( dev
, rgn
);
977 static COLORREF
windrv_SetPixel( PHYSDEV dev
, INT x
, INT y
, COLORREF color
)
979 struct windrv_physdev
*physdev
= get_windrv_physdev( dev
);
982 lock_surface( physdev
);
983 dev
= GET_NEXT_PHYSDEV( dev
, pSetPixel
);
984 ret
= dev
->funcs
->pSetPixel( dev
, x
, y
, color
);
985 unlock_surface( physdev
);
989 static BOOL
windrv_StretchBlt( PHYSDEV dst_dev
, struct bitblt_coords
*dst
,
990 PHYSDEV src_dev
, struct bitblt_coords
*src
, DWORD rop
)
992 struct windrv_physdev
*physdev
= get_windrv_physdev( dst_dev
);
995 lock_surface( physdev
);
996 dst_dev
= GET_NEXT_PHYSDEV( dst_dev
, pStretchBlt
);
997 ret
= dst_dev
->funcs
->pStretchBlt( dst_dev
, dst
, src_dev
, src
, rop
);
998 unlock_surface( physdev
);
1002 static INT
windrv_StretchDIBits( PHYSDEV dev
, INT x_dst
, INT y_dst
, INT width_dst
, INT height_dst
,
1003 INT x_src
, INT y_src
, INT width_src
, INT height_src
, const void *bits
,
1004 BITMAPINFO
*src_info
, UINT coloruse
, DWORD rop
)
1006 struct windrv_physdev
*physdev
= get_windrv_physdev( dev
);
1009 lock_surface( physdev
);
1010 dev
= GET_NEXT_PHYSDEV( dev
, pStretchDIBits
);
1011 ret
= dev
->funcs
->pStretchDIBits( dev
, x_dst
, y_dst
, width_dst
, height_dst
,
1012 x_src
, y_src
, width_src
, height_src
, bits
, src_info
, coloruse
, rop
);
1013 unlock_surface( physdev
);
1017 static struct opengl_funcs
*windrv_wine_get_wgl_driver( PHYSDEV dev
, UINT version
)
1019 dev
= GET_NEXT_PHYSDEV( dev
, wine_get_wgl_driver
);
1020 if (dev
->funcs
== &dib_driver
) dev
= GET_NEXT_PHYSDEV( dev
, wine_get_wgl_driver
);
1021 return dev
->funcs
->wine_get_wgl_driver( dev
, version
);
1024 static const struct gdi_dc_funcs window_driver
=
1026 NULL
, /* pAbortDoc */
1027 NULL
, /* pAbortPath */
1028 windrv_AlphaBlend
, /* pAlphaBlend */
1029 NULL
, /* pAngleArc */
1030 windrv_Arc
, /* pArc */
1031 windrv_ArcTo
, /* pArcTo */
1032 NULL
, /* pBeginPath */
1033 windrv_BlendImage
, /* pBlendImage */
1034 windrv_Chord
, /* pChord */
1035 NULL
, /* pCloseFigure */
1036 NULL
, /* pCreateCompatibleDC */
1037 windrv_CreateDC
, /* pCreateDC */
1038 windrv_DeleteDC
, /* pDeleteDC */
1039 NULL
, /* pDeleteObject */
1040 NULL
, /* pDeviceCapabilities */
1041 windrv_Ellipse
, /* pEllipse */
1043 NULL
, /* pEndPage */
1044 NULL
, /* pEndPath */
1045 NULL
, /* pEnumFonts */
1046 NULL
, /* pEnumICMProfiles */
1047 NULL
, /* pExcludeClipRect */
1048 NULL
, /* pExtDeviceMode */
1049 NULL
, /* pExtEscape */
1050 windrv_ExtFloodFill
, /* pExtFloodFill */
1051 NULL
, /* pExtSelectClipRgn */
1052 windrv_ExtTextOut
, /* pExtTextOut */
1053 NULL
, /* pFillPath */
1054 NULL
, /* pFillRgn */
1055 NULL
, /* pFlattenPath */
1056 NULL
, /* pFontIsLinked */
1057 NULL
, /* pFrameRgn */
1058 NULL
, /* pGdiComment */
1059 NULL
, /* pGetBoundsRect */
1060 NULL
, /* pGetCharABCWidths */
1061 NULL
, /* pGetCharABCWidthsI */
1062 NULL
, /* pGetCharWidth */
1063 NULL
, /* pGetDeviceCaps */
1064 NULL
, /* pGetDeviceGammaRamp */
1065 NULL
, /* pGetFontData */
1066 NULL
, /* pGetFontRealizationInfo */
1067 NULL
, /* pGetFontUnicodeRanges */
1068 NULL
, /* pGetGlyphIndices */
1069 NULL
, /* pGetGlyphOutline */
1070 NULL
, /* pGetICMProfile */
1071 windrv_GetImage
, /* pGetImage */
1072 NULL
, /* pGetKerningPairs */
1073 NULL
, /* pGetNearestColor */
1074 NULL
, /* pGetOutlineTextMetrics */
1075 windrv_GetPixel
, /* pGetPixel */
1076 NULL
, /* pGetSystemPaletteEntries */
1077 NULL
, /* pGetTextCharsetInfo */
1078 NULL
, /* pGetTextExtentExPoint */
1079 NULL
, /* pGetTextExtentExPointI */
1080 NULL
, /* pGetTextFace */
1081 NULL
, /* pGetTextMetrics */
1082 windrv_GradientFill
, /* pGradientFill */
1083 NULL
, /* pIntersectClipRect */
1084 NULL
, /* pInvertRgn */
1085 windrv_LineTo
, /* pLineTo */
1086 NULL
, /* pModifyWorldTransform */
1088 NULL
, /* pOffsetClipRgn */
1089 NULL
, /* pOffsetViewportOrg */
1090 NULL
, /* pOffsetWindowOrg */
1091 windrv_PaintRgn
, /* pPaintRgn */
1092 windrv_PatBlt
, /* pPatBlt */
1093 windrv_Pie
, /* pPie */
1094 NULL
, /* pPolyBezier */
1095 NULL
, /* pPolyBezierTo */
1096 NULL
, /* pPolyDraw */
1097 windrv_PolyPolygon
, /* pPolyPolygon */
1098 windrv_PolyPolyline
, /* pPolyPolyline */
1099 windrv_Polygon
, /* pPolygon */
1100 windrv_Polyline
, /* pPolyline */
1101 NULL
, /* pPolylineTo */
1102 windrv_PutImage
, /* pPutImage */
1103 NULL
, /* pRealizeDefaultPalette */
1104 NULL
, /* pRealizePalette */
1105 windrv_Rectangle
, /* pRectangle */
1106 NULL
, /* pResetDC */
1107 NULL
, /* pRestoreDC */
1108 windrv_RoundRect
, /* pRoundRect */
1110 NULL
, /* pScaleViewportExt */
1111 NULL
, /* pScaleWindowExt */
1112 NULL
, /* pSelectBitmap */
1113 NULL
, /* pSelectBrush */
1114 NULL
, /* pSelectClipPath */
1115 NULL
, /* pSelectFont */
1116 NULL
, /* pSelectPalette */
1117 NULL
, /* pSelectPen */
1118 NULL
, /* pSetArcDirection */
1119 NULL
, /* pSetBkColor */
1120 NULL
, /* pSetBkMode */
1121 windrv_SetBoundsRect
, /* pSetBoundsRect */
1122 NULL
, /* pSetDCBrushColor */
1123 NULL
, /* pSetDCPenColor */
1124 windrv_SetDIBitsToDevice
, /* pSetDIBitsToDevice */
1125 windrv_SetDeviceClipping
, /* pSetDeviceClipping */
1126 NULL
, /* pSetDeviceGammaRamp */
1127 NULL
, /* pSetLayout */
1128 NULL
, /* pSetMapMode */
1129 NULL
, /* pSetMapperFlags */
1130 windrv_SetPixel
, /* pSetPixel */
1131 NULL
, /* pSetPolyFillMode */
1132 NULL
, /* pSetROP2 */
1133 NULL
, /* pSetRelAbs */
1134 NULL
, /* pSetStretchBltMode */
1135 NULL
, /* pSetTextAlign */
1136 NULL
, /* pSetTextCharacterExtra */
1137 NULL
, /* pSetTextColor */
1138 NULL
, /* pSetTextJustification */
1139 NULL
, /* pSetViewportExt */
1140 NULL
, /* pSetViewportOrg */
1141 NULL
, /* pSetWindowExt */
1142 NULL
, /* pSetWindowOrg */
1143 NULL
, /* pSetWorldTransform */
1144 NULL
, /* pStartDoc */
1145 NULL
, /* pStartPage */
1146 windrv_StretchBlt
, /* pStretchBlt */
1147 windrv_StretchDIBits
, /* pStretchDIBits */
1148 NULL
, /* pStrokeAndFillPath */
1149 NULL
, /* pStrokePath */
1150 NULL
, /* pUnrealizePalette */
1151 NULL
, /* pWidenPath */
1152 windrv_wine_get_wgl_driver
, /* wine_get_wgl_driver */
1153 GDI_PRIORITY_DIB_DRV
+ 10 /* priority */