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
, const DWORD
*bit_fields
,
71 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
;
81 dib
->stride
= get_dib_stride( dib
->width
, dib
->bit_count
);
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
, (const DWORD
*)info
->bmiColors
, info
->bmiColors
, bits
);
160 BOOL
init_dib_info_from_bitmapobj(dib_info
*dib
, BITMAPOBJ
*bmp
)
162 if (!is_bitmapobj_dib( bmp
))
166 get_ddb_bitmapinfo( bmp
, &info
);
167 if (!bmp
->dib
.dsBm
.bmBits
)
169 int width_bytes
= get_dib_stride( bmp
->dib
.dsBm
.bmWidth
, bmp
->dib
.dsBm
.bmBitsPixel
);
170 bmp
->dib
.dsBm
.bmBits
= HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY
,
171 bmp
->dib
.dsBm
.bmHeight
* width_bytes
);
172 if (!bmp
->dib
.dsBm
.bmBits
) return FALSE
;
174 init_dib_info_from_bitmapinfo( dib
, &info
, bmp
->dib
.dsBm
.bmBits
);
176 else init_dib_info( dib
, &bmp
->dib
.dsBmih
, bmp
->dib
.dsBitfields
,
177 bmp
->color_table
, bmp
->dib
.dsBm
.bmBits
);
181 static void clear_dib_info(dib_info
*dib
)
183 dib
->bits
.ptr
= NULL
;
184 dib
->bits
.free
= NULL
;
185 dib
->bits
.param
= NULL
;
188 /**********************************************************************
191 * Free the resources associated with a dib and optionally the bits
193 void free_dib_info(dib_info
*dib
)
195 if (dib
->bits
.free
) dib
->bits
.free( &dib
->bits
);
196 clear_dib_info( dib
);
199 void copy_dib_color_info(dib_info
*dst
, const dib_info
*src
)
201 dst
->bit_count
= src
->bit_count
;
202 dst
->red_mask
= src
->red_mask
;
203 dst
->green_mask
= src
->green_mask
;
204 dst
->blue_mask
= src
->blue_mask
;
205 dst
->red_len
= src
->red_len
;
206 dst
->green_len
= src
->green_len
;
207 dst
->blue_len
= src
->blue_len
;
208 dst
->red_shift
= src
->red_shift
;
209 dst
->green_shift
= src
->green_shift
;
210 dst
->blue_shift
= src
->blue_shift
;
211 dst
->funcs
= src
->funcs
;
212 dst
->color_table_size
= src
->color_table_size
;
213 dst
->color_table
= src
->color_table
;
216 DWORD
convert_bitmapinfo( const BITMAPINFO
*src_info
, void *src_bits
, struct bitblt_coords
*src
,
217 const BITMAPINFO
*dst_info
, void *dst_bits
)
219 dib_info src_dib
, dst_dib
;
222 init_dib_info_from_bitmapinfo( &src_dib
, src_info
, src_bits
);
223 init_dib_info_from_bitmapinfo( &dst_dib
, dst_info
, dst_bits
);
227 dst_dib
.funcs
->convert_to( &dst_dib
, &src_dib
, &src
->visrect
, FALSE
);
232 WARN( "invalid bits pointer %p\n", src_bits
);
237 if(!ret
) return ERROR_BAD_FORMAT
;
239 /* update coordinates, the destination rectangle is always stored at 0,0 */
240 src
->x
-= src
->visrect
.left
;
241 src
->y
-= src
->visrect
.top
;
242 offset_rect( &src
->visrect
, -src
->visrect
.left
, -src
->visrect
.top
);
243 return ERROR_SUCCESS
;
246 int clip_rect_to_dib( const dib_info
*dib
, RECT
*rc
)
250 rect
.left
= max( 0, -dib
->rect
.left
);
251 rect
.top
= max( 0, -dib
->rect
.top
);
252 rect
.right
= min( dib
->rect
.right
, dib
->width
) - dib
->rect
.left
;
253 rect
.bottom
= min( dib
->rect
.bottom
, dib
->height
) - dib
->rect
.top
;
254 if (is_rect_empty( &rect
)) return 0;
255 return intersect_rect( rc
, &rect
, rc
);
258 int get_clipped_rects( const dib_info
*dib
, const RECT
*rc
, HRGN clip
, struct clipped_rects
*clip_rects
)
260 const WINEREGION
*region
;
261 RECT rect
, *out
= clip_rects
->buffer
;
264 init_clipped_rects( clip_rects
);
266 rect
.left
= max( 0, -dib
->rect
.left
);
267 rect
.top
= max( 0, -dib
->rect
.top
);
268 rect
.right
= min( dib
->rect
.right
, dib
->width
) - dib
->rect
.left
;
269 rect
.bottom
= min( dib
->rect
.bottom
, dib
->height
) - dib
->rect
.top
;
270 if (is_rect_empty( &rect
)) return 0;
271 if (rc
&& !intersect_rect( &rect
, &rect
, rc
)) return 0;
276 clip_rects
->count
= 1;
280 if (!(region
= get_wine_region( clip
))) return 0;
282 for (i
= 0; i
< region
->numRects
; i
++)
284 if (region
->rects
[i
].top
>= rect
.bottom
) break;
285 if (!intersect_rect( out
, &rect
, ®ion
->rects
[i
] )) continue;
287 if (out
== &clip_rects
->buffer
[sizeof(clip_rects
->buffer
) / sizeof(RECT
)])
289 clip_rects
->rects
= HeapAlloc( GetProcessHeap(), 0, region
->numRects
* sizeof(RECT
) );
290 if (!clip_rects
->rects
) return 0;
291 memcpy( clip_rects
->rects
, clip_rects
->buffer
, (out
- clip_rects
->buffer
) * sizeof(RECT
) );
292 out
= clip_rects
->rects
+ (out
- clip_rects
->buffer
);
295 release_wine_region( clip
);
296 clip_rects
->count
= out
- clip_rects
->rects
;
297 return clip_rects
->count
;
300 void add_clipped_bounds( dibdrv_physdev
*dev
, const RECT
*rect
, HRGN clip
)
302 const WINEREGION
*region
;
305 if (!dev
->bounds
) return;
308 if (!(region
= get_wine_region( clip
))) return;
309 if (!rect
) rc
= region
->extents
;
310 else intersect_rect( &rc
, rect
, ®ion
->extents
);
311 release_wine_region( clip
);
315 if (is_rect_empty( &rc
)) return;
316 offset_rect( &rc
, dev
->dib
.rect
.left
, dev
->dib
.rect
.top
);
317 add_bounds_rect( dev
->bounds
, &rc
);
320 /**********************************************************************
323 static BOOL
dibdrv_CreateDC( PHYSDEV
*dev
, LPCWSTR driver
, LPCWSTR device
,
324 LPCWSTR output
, const DEVMODEW
*data
)
326 dibdrv_physdev
*pdev
= HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(*pdev
) );
328 if (!pdev
) return FALSE
;
329 clear_dib_info(&pdev
->dib
);
330 clear_dib_info(&pdev
->brush
.dib
);
331 clear_dib_info(&pdev
->pen_brush
.dib
);
332 push_dc_driver( dev
, &pdev
->dev
, &dib_driver
);
336 /***********************************************************************
339 static BOOL
dibdrv_DeleteDC( PHYSDEV dev
)
341 dibdrv_physdev
*pdev
= get_dibdrv_pdev(dev
);
342 TRACE("(%p)\n", dev
);
343 free_pattern_brush( &pdev
->brush
);
344 free_pattern_brush( &pdev
->pen_brush
);
345 release_cached_font( pdev
->font
);
346 HeapFree( GetProcessHeap(), 0, pdev
);
350 /***********************************************************************
351 * dibdrv_SelectBitmap
353 static HBITMAP
dibdrv_SelectBitmap( PHYSDEV dev
, HBITMAP bitmap
)
355 dibdrv_physdev
*pdev
= get_dibdrv_pdev(dev
);
356 BITMAPOBJ
*bmp
= GDI_GetObjPtr( bitmap
, OBJ_BITMAP
);
359 TRACE("(%p, %p)\n", dev
, bitmap
);
363 if (!init_dib_info_from_bitmapobj(&dib
, bmp
))
365 GDI_ReleaseObj( bitmap
);
369 GDI_ReleaseObj( bitmap
);
374 /***********************************************************************
375 * dibdrv_SetDeviceClipping
377 static void dibdrv_SetDeviceClipping( PHYSDEV dev
, HRGN rgn
)
379 dibdrv_physdev
*pdev
= get_dibdrv_pdev(dev
);
380 TRACE("(%p, %p)\n", dev
, rgn
);
385 /***********************************************************************
386 * dibdrv_SetBoundsRect
388 static UINT
dibdrv_SetBoundsRect( PHYSDEV dev
, RECT
*rect
, UINT flags
)
390 dibdrv_physdev
*pdev
= get_dibdrv_pdev( dev
);
392 if (flags
& DCB_DISABLE
) pdev
->bounds
= NULL
;
393 else if (flags
& DCB_ENABLE
) pdev
->bounds
= rect
;
394 return DCB_RESET
; /* we don't have device-specific bounds */
397 const struct gdi_dc_funcs dib_driver
=
399 NULL
, /* pAbortDoc */
400 NULL
, /* pAbortPath */
401 dibdrv_AlphaBlend
, /* pAlphaBlend */
402 NULL
, /* pAngleArc */
403 dibdrv_Arc
, /* pArc */
404 dibdrv_ArcTo
, /* pArcTo */
405 NULL
, /* pBeginPath */
406 dibdrv_BlendImage
, /* pBlendImage */
407 dibdrv_Chord
, /* pChord */
408 NULL
, /* pCloseFigure */
409 NULL
, /* pCreateCompatibleDC */
410 dibdrv_CreateDC
, /* pCreateDC */
411 dibdrv_DeleteDC
, /* pDeleteDC */
412 NULL
, /* pDeleteObject */
413 NULL
, /* pDeviceCapabilities */
414 dibdrv_Ellipse
, /* pEllipse */
418 NULL
, /* pEnumFonts */
419 NULL
, /* pEnumICMProfiles */
420 NULL
, /* pExcludeClipRect */
421 NULL
, /* pExtDeviceMode */
422 NULL
, /* pExtEscape */
423 dibdrv_ExtFloodFill
, /* pExtFloodFill */
424 NULL
, /* pExtSelectClipRgn */
425 dibdrv_ExtTextOut
, /* pExtTextOut */
426 NULL
, /* pFillPath */
428 NULL
, /* pFlattenPath */
429 NULL
, /* pFontIsLinked */
430 NULL
, /* pFrameRgn */
431 NULL
, /* pGdiComment */
432 NULL
, /* pGdiRealizationInfo */
433 NULL
, /* pGetBoundsRect */
434 NULL
, /* pGetCharABCWidths */
435 NULL
, /* pGetCharABCWidthsI */
436 NULL
, /* pGetCharWidth */
437 NULL
, /* pGetDeviceCaps */
438 NULL
, /* pGetDeviceGammaRamp */
439 NULL
, /* pGetFontData */
440 NULL
, /* pGetFontUnicodeRanges */
441 NULL
, /* pGetGlyphIndices */
442 NULL
, /* pGetGlyphOutline */
443 NULL
, /* pGetICMProfile */
444 dibdrv_GetImage
, /* pGetImage */
445 NULL
, /* pGetKerningPairs */
446 dibdrv_GetNearestColor
, /* pGetNearestColor */
447 NULL
, /* pGetOutlineTextMetrics */
448 dibdrv_GetPixel
, /* pGetPixel */
449 NULL
, /* pGetSystemPaletteEntries */
450 NULL
, /* pGetTextCharsetInfo */
451 NULL
, /* pGetTextExtentExPoint */
452 NULL
, /* pGetTextExtentExPointI */
453 NULL
, /* pGetTextFace */
454 NULL
, /* pGetTextMetrics */
455 dibdrv_GradientFill
, /* pGradientFill */
456 NULL
, /* pIntersectClipRect */
457 NULL
, /* pInvertRgn */
458 dibdrv_LineTo
, /* pLineTo */
459 NULL
, /* pModifyWorldTransform */
461 NULL
, /* pOffsetClipRgn */
462 NULL
, /* pOffsetViewportOrg */
463 NULL
, /* pOffsetWindowOrg */
464 dibdrv_PaintRgn
, /* pPaintRgn */
465 dibdrv_PatBlt
, /* pPatBlt */
466 dibdrv_Pie
, /* pPie */
467 NULL
, /* pPolyBezier */
468 NULL
, /* pPolyBezierTo */
469 NULL
, /* pPolyDraw */
470 dibdrv_PolyPolygon
, /* pPolyPolygon */
471 dibdrv_PolyPolyline
, /* pPolyPolyline */
472 dibdrv_Polygon
, /* pPolygon */
473 dibdrv_Polyline
, /* pPolyline */
474 NULL
, /* pPolylineTo */
475 dibdrv_PutImage
, /* pPutImage */
476 NULL
, /* pRealizeDefaultPalette */
477 NULL
, /* pRealizePalette */
478 dibdrv_Rectangle
, /* pRectangle */
480 NULL
, /* pRestoreDC */
481 dibdrv_RoundRect
, /* pRoundRect */
483 NULL
, /* pScaleViewportExt */
484 NULL
, /* pScaleWindowExt */
485 dibdrv_SelectBitmap
, /* pSelectBitmap */
486 dibdrv_SelectBrush
, /* pSelectBrush */
487 NULL
, /* pSelectClipPath */
488 dibdrv_SelectFont
, /* pSelectFont */
489 NULL
, /* pSelectPalette */
490 dibdrv_SelectPen
, /* pSelectPen */
491 NULL
, /* pSetArcDirection */
492 NULL
, /* pSetBkColor */
493 NULL
, /* pSetBkMode */
494 dibdrv_SetBoundsRect
, /* pSetBoundsRect */
495 dibdrv_SetDCBrushColor
, /* pSetDCBrushColor */
496 dibdrv_SetDCPenColor
, /* pSetDCPenColor */
497 NULL
, /* pSetDIBitsToDevice */
498 dibdrv_SetDeviceClipping
, /* pSetDeviceClipping */
499 NULL
, /* pSetDeviceGammaRamp */
500 NULL
, /* pSetLayout */
501 NULL
, /* pSetMapMode */
502 NULL
, /* pSetMapperFlags */
503 dibdrv_SetPixel
, /* pSetPixel */
504 NULL
, /* pSetPolyFillMode */
506 NULL
, /* pSetRelAbs */
507 NULL
, /* pSetStretchBltMode */
508 NULL
, /* pSetTextAlign */
509 NULL
, /* pSetTextCharacterExtra */
510 NULL
, /* pSetTextColor */
511 NULL
, /* pSetTextJustification */
512 NULL
, /* pSetViewportExt */
513 NULL
, /* pSetViewportOrg */
514 NULL
, /* pSetWindowExt */
515 NULL
, /* pSetWindowOrg */
516 NULL
, /* pSetWorldTransform */
517 NULL
, /* pStartDoc */
518 NULL
, /* pStartPage */
519 dibdrv_StretchBlt
, /* pStretchBlt */
520 NULL
, /* pStretchDIBits */
521 NULL
, /* pStrokeAndFillPath */
522 NULL
, /* pStrokePath */
523 NULL
, /* pUnrealizePalette */
524 NULL
, /* pWidenPath */
525 dibdrv_wine_get_wgl_driver
, /* wine_get_wgl_driver */
526 GDI_PRIORITY_DIB_DRV
/* priority */
530 /***********************************************************************
531 * Driver for window surfaces.
533 * It uses the DIB engine but needs extra locking since multiple DCs
534 * can paint to the same window.
537 struct windrv_physdev
539 struct gdi_physdev dev
;
540 struct dibdrv_physdev
*dibdrv
;
541 struct window_surface
*surface
;
544 static const struct gdi_dc_funcs window_driver
;
546 static inline struct windrv_physdev
*get_windrv_physdev( PHYSDEV dev
)
548 return (struct windrv_physdev
*)dev
;
551 static inline void lock_surface( struct window_surface
*surface
)
554 surface
->funcs
->lock( surface
);
557 static inline void unlock_surface( struct window_surface
*surface
)
559 surface
->funcs
->unlock( surface
);
562 static void unlock_bits_surface( struct gdi_image_bits
*bits
)
564 unlock_surface( bits
->param
);
567 void dibdrv_set_window_surface( DC
*dc
, struct window_surface
*surface
)
569 char buffer
[FIELD_OFFSET( BITMAPINFO
, bmiColors
[256] )];
570 BITMAPINFO
*info
= (BITMAPINFO
*)buffer
;
574 struct windrv_physdev
*physdev
;
575 struct dibdrv_physdev
*dibdrv
;
577 TRACE( "%p %p\n", dc
->hSelf
, surface
);
579 windev
= pop_dc_driver( dc
, &window_driver
);
583 if (windev
) push_dc_driver( &dc
->physDev
, windev
, windev
->funcs
);
586 if (!window_driver
.pCreateDC( &dc
->physDev
, NULL
, NULL
, NULL
, NULL
)) return;
587 windev
= find_dc_driver( dc
, &window_driver
);
590 physdev
= get_windrv_physdev( windev
);
591 window_surface_add_ref( surface
);
592 if (physdev
->surface
) window_surface_release( physdev
->surface
);
593 physdev
->surface
= surface
;
595 dibdrv
= physdev
->dibdrv
;
596 bits
= surface
->funcs
->get_info( surface
, info
);
597 init_dib_info_from_bitmapinfo( &dibdrv
->dib
, info
, bits
);
598 /* clip the device rect to the surface */
599 rect
= surface
->rect
;
600 offset_rect( &rect
, dc
->device_rect
.left
, dc
->device_rect
.top
);
601 intersect_rect( &dc
->device_rect
, &dc
->device_rect
, &rect
);
602 dibdrv
->dib
.rect
= dc
->vis_rect
;
603 offset_rect( &dibdrv
->dib
.rect
, -rect
.left
, -rect
.top
);
604 dibdrv
->bounds
= surface
->funcs
->get_bounds( surface
);
609 dib_driver
.pDeleteDC( pop_dc_driver( dc
, &dib_driver
));
610 windev
->funcs
->pDeleteDC( windev
);
615 static BOOL
windrv_AlphaBlend( PHYSDEV dst_dev
, struct bitblt_coords
*dst
,
616 PHYSDEV src_dev
, struct bitblt_coords
*src
, BLENDFUNCTION func
)
618 struct windrv_physdev
*physdev
= get_windrv_physdev( dst_dev
);
621 lock_surface( physdev
->surface
);
622 dst_dev
= GET_NEXT_PHYSDEV( dst_dev
, pAlphaBlend
);
623 ret
= dst_dev
->funcs
->pAlphaBlend( dst_dev
, dst
, src_dev
, src
, func
);
624 unlock_surface( physdev
->surface
);
628 static BOOL
windrv_Arc( PHYSDEV dev
, INT left
, INT top
, INT right
, INT bottom
,
629 INT xstart
, INT ystart
, INT xend
, INT yend
)
631 struct windrv_physdev
*physdev
= get_windrv_physdev( dev
);
634 lock_surface( physdev
->surface
);
635 dev
= GET_NEXT_PHYSDEV( dev
, pArc
);
636 ret
= dev
->funcs
->pArc( dev
, left
, top
, right
, bottom
, xstart
, ystart
, xend
, yend
);
637 unlock_surface( physdev
->surface
);
641 static BOOL
windrv_ArcTo( PHYSDEV dev
, INT left
, INT top
, INT right
, INT bottom
,
642 INT xstart
, INT ystart
, INT xend
, INT yend
)
644 struct windrv_physdev
*physdev
= get_windrv_physdev( dev
);
647 lock_surface( physdev
->surface
);
648 dev
= GET_NEXT_PHYSDEV( dev
, pArc
);
649 ret
= dev
->funcs
->pArcTo( dev
, left
, top
, right
, bottom
, xstart
, ystart
, xend
, yend
);
650 unlock_surface( physdev
->surface
);
654 static DWORD
windrv_BlendImage( PHYSDEV dev
, BITMAPINFO
*info
, const struct gdi_image_bits
*bits
,
655 struct bitblt_coords
*src
, struct bitblt_coords
*dst
, BLENDFUNCTION blend
)
657 struct windrv_physdev
*physdev
= get_windrv_physdev( dev
);
660 lock_surface( physdev
->surface
);
661 dev
= GET_NEXT_PHYSDEV( dev
, pBlendImage
);
662 ret
= dev
->funcs
->pBlendImage( dev
, info
, bits
, src
, dst
, blend
);
663 unlock_surface( physdev
->surface
);
667 static BOOL
windrv_Chord( PHYSDEV dev
, INT left
, INT top
, INT right
, INT bottom
,
668 INT xstart
, INT ystart
, INT xend
, INT yend
)
670 struct windrv_physdev
*physdev
= get_windrv_physdev( dev
);
673 lock_surface( physdev
->surface
);
674 dev
= GET_NEXT_PHYSDEV( dev
, pChord
);
675 ret
= dev
->funcs
->pChord( dev
, left
, top
, right
, bottom
, xstart
, ystart
, xend
, yend
);
676 unlock_surface( physdev
->surface
);
680 static BOOL
windrv_CreateDC( PHYSDEV
*dev
, LPCWSTR driver
, LPCWSTR device
,
681 LPCWSTR output
, const DEVMODEW
*devmode
)
683 struct windrv_physdev
*physdev
= HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(*physdev
) );
685 if (!physdev
) return FALSE
;
687 if (!dib_driver
.pCreateDC( dev
, NULL
, NULL
, NULL
, NULL
))
689 HeapFree( GetProcessHeap(), 0, physdev
);
692 physdev
->dibdrv
= get_dibdrv_pdev( *dev
);
693 push_dc_driver( dev
, &physdev
->dev
, &window_driver
);
697 static BOOL
windrv_DeleteDC( PHYSDEV dev
)
699 struct windrv_physdev
*physdev
= get_windrv_physdev( dev
);
701 window_surface_release( physdev
->surface
);
702 HeapFree( GetProcessHeap(), 0, physdev
);
706 static BOOL
windrv_Ellipse( PHYSDEV dev
, INT left
, INT top
, INT right
, INT bottom
)
708 struct windrv_physdev
*physdev
= get_windrv_physdev( dev
);
711 lock_surface( physdev
->surface
);
712 dev
= GET_NEXT_PHYSDEV( dev
, pEllipse
);
713 ret
= dev
->funcs
->pEllipse( dev
, left
, top
, right
, bottom
);
714 unlock_surface( physdev
->surface
);
718 static BOOL
windrv_ExtFloodFill( PHYSDEV dev
, INT x
, INT y
, COLORREF color
, UINT type
)
720 struct windrv_physdev
*physdev
= get_windrv_physdev( dev
);
723 lock_surface( physdev
->surface
);
724 dev
= GET_NEXT_PHYSDEV( dev
, pExtFloodFill
);
725 ret
= dev
->funcs
->pExtFloodFill( dev
, x
, y
, color
, type
);
726 unlock_surface( physdev
->surface
);
730 static BOOL
windrv_ExtTextOut( PHYSDEV dev
, INT x
, INT y
, UINT flags
, const RECT
*rect
,
731 LPCWSTR str
, UINT count
, const INT
*dx
)
733 struct windrv_physdev
*physdev
= get_windrv_physdev( dev
);
736 lock_surface( physdev
->surface
);
737 dev
= GET_NEXT_PHYSDEV( dev
, pExtTextOut
);
738 ret
= dev
->funcs
->pExtTextOut( dev
, x
, y
, flags
, rect
, str
, count
, dx
);
739 unlock_surface( physdev
->surface
);
743 static DWORD
windrv_GetImage( PHYSDEV dev
, BITMAPINFO
*info
,
744 struct gdi_image_bits
*bits
, struct bitblt_coords
*src
)
746 struct windrv_physdev
*physdev
= get_windrv_physdev( dev
);
749 lock_surface( physdev
->surface
);
750 dev
= GET_NEXT_PHYSDEV( dev
, pGetImage
);
751 ret
= dev
->funcs
->pGetImage( dev
, info
, bits
, src
);
753 /* don't return alpha if original surface doesn't support it */
754 if (info
->bmiHeader
.biBitCount
== 32 &&
755 info
->bmiHeader
.biCompression
== BI_RGB
&&
756 physdev
->dibdrv
->dib
.compression
== BI_BITFIELDS
)
758 DWORD
*colors
= (DWORD
*)info
->bmiColors
;
759 colors
[0] = 0xff0000;
760 colors
[1] = 0x00ff00;
761 colors
[2] = 0x0000ff;
762 info
->bmiHeader
.biCompression
= BI_BITFIELDS
;
767 /* use the freeing callback to unlock the surface */
768 assert( !bits
->free
);
769 bits
->free
= unlock_bits_surface
;
770 bits
->param
= physdev
->surface
;
772 else unlock_surface( physdev
->surface
);
776 static COLORREF
windrv_GetPixel( PHYSDEV dev
, INT x
, INT y
)
778 struct windrv_physdev
*physdev
= get_windrv_physdev( dev
);
781 lock_surface( physdev
->surface
);
782 dev
= GET_NEXT_PHYSDEV( dev
, pGetPixel
);
783 ret
= dev
->funcs
->pGetPixel( dev
, x
, y
);
784 unlock_surface( physdev
->surface
);
788 static BOOL
windrv_GradientFill( PHYSDEV dev
, TRIVERTEX
*vert_array
, ULONG nvert
,
789 void * grad_array
, ULONG ngrad
, ULONG mode
)
791 struct windrv_physdev
*physdev
= get_windrv_physdev( dev
);
794 lock_surface( physdev
->surface
);
795 dev
= GET_NEXT_PHYSDEV( dev
, pGradientFill
);
796 ret
= dev
->funcs
->pGradientFill( dev
, vert_array
, nvert
, grad_array
, ngrad
, mode
);
797 unlock_surface( physdev
->surface
);
801 static BOOL
windrv_LineTo( PHYSDEV dev
, INT x
, INT y
)
803 struct windrv_physdev
*physdev
= get_windrv_physdev( dev
);
806 lock_surface( physdev
->surface
);
807 dev
= GET_NEXT_PHYSDEV( dev
, pLineTo
);
808 ret
= dev
->funcs
->pLineTo( dev
, x
, y
);
809 unlock_surface( physdev
->surface
);
813 static BOOL
windrv_PaintRgn( PHYSDEV dev
, HRGN rgn
)
815 struct windrv_physdev
*physdev
= get_windrv_physdev( dev
);
818 lock_surface( physdev
->surface
);
819 dev
= GET_NEXT_PHYSDEV( dev
, pPaintRgn
);
820 ret
= dev
->funcs
->pPaintRgn( dev
, rgn
);
821 unlock_surface( physdev
->surface
);
825 static BOOL
windrv_PatBlt( PHYSDEV dev
, struct bitblt_coords
*dst
, DWORD rop
)
827 struct windrv_physdev
*physdev
= get_windrv_physdev( dev
);
830 lock_surface( physdev
->surface
);
831 dev
= GET_NEXT_PHYSDEV( dev
, pPatBlt
);
832 ret
= dev
->funcs
->pPatBlt( dev
, dst
, rop
);
833 unlock_surface( physdev
->surface
);
837 static BOOL
windrv_Pie( PHYSDEV dev
, INT left
, INT top
, INT right
, INT bottom
,
838 INT xstart
, INT ystart
, INT xend
, INT yend
)
840 struct windrv_physdev
*physdev
= get_windrv_physdev( dev
);
843 lock_surface( physdev
->surface
);
844 dev
= GET_NEXT_PHYSDEV( dev
, pPie
);
845 ret
= dev
->funcs
->pPie( dev
, left
, top
, right
, bottom
, xstart
, ystart
, xend
, yend
);
846 unlock_surface( physdev
->surface
);
850 static BOOL
windrv_PolyPolygon( PHYSDEV dev
, const POINT
*points
, const INT
*counts
, UINT polygons
)
852 struct windrv_physdev
*physdev
= get_windrv_physdev( dev
);
855 lock_surface( physdev
->surface
);
856 dev
= GET_NEXT_PHYSDEV( dev
, pPolyPolygon
);
857 ret
= dev
->funcs
->pPolyPolygon( dev
, points
, counts
, polygons
);
858 unlock_surface( physdev
->surface
);
862 static BOOL
windrv_PolyPolyline( PHYSDEV dev
, const POINT
*points
, const DWORD
*counts
, DWORD lines
)
864 struct windrv_physdev
*physdev
= get_windrv_physdev( dev
);
867 lock_surface( physdev
->surface
);
868 dev
= GET_NEXT_PHYSDEV( dev
, pPolyPolyline
);
869 ret
= dev
->funcs
->pPolyPolyline( dev
, points
, counts
, lines
);
870 unlock_surface( physdev
->surface
);
874 static BOOL
windrv_Polygon( PHYSDEV dev
, const POINT
*points
, INT count
)
876 struct windrv_physdev
*physdev
= get_windrv_physdev( dev
);
879 lock_surface( physdev
->surface
);
880 dev
= GET_NEXT_PHYSDEV( dev
, pPolygon
);
881 ret
= dev
->funcs
->pPolygon( dev
, points
, count
);
882 unlock_surface( physdev
->surface
);
886 static BOOL
windrv_Polyline( PHYSDEV dev
, const POINT
*points
, INT count
)
888 struct windrv_physdev
*physdev
= get_windrv_physdev( dev
);
891 lock_surface( physdev
->surface
);
892 dev
= GET_NEXT_PHYSDEV( dev
, pPolyline
);
893 ret
= dev
->funcs
->pPolyline( dev
, points
, count
);
894 unlock_surface( physdev
->surface
);
898 static DWORD
windrv_PutImage( PHYSDEV dev
, HRGN clip
, BITMAPINFO
*info
,
899 const struct gdi_image_bits
*bits
, struct bitblt_coords
*src
,
900 struct bitblt_coords
*dst
, DWORD rop
)
902 struct windrv_physdev
*physdev
= get_windrv_physdev( dev
);
905 lock_surface( physdev
->surface
);
906 dev
= GET_NEXT_PHYSDEV( dev
, pPutImage
);
907 ret
= dev
->funcs
->pPutImage( dev
, clip
, info
, bits
, src
, dst
, rop
);
908 unlock_surface( physdev
->surface
);
912 static BOOL
windrv_Rectangle( PHYSDEV dev
, INT left
, INT top
, INT right
, INT bottom
)
914 struct windrv_physdev
*physdev
= get_windrv_physdev( dev
);
917 lock_surface( physdev
->surface
);
918 dev
= GET_NEXT_PHYSDEV( dev
, pRectangle
);
919 ret
= dev
->funcs
->pRectangle( dev
, left
, top
, right
, bottom
);
920 unlock_surface( physdev
->surface
);
924 static BOOL
windrv_RoundRect( PHYSDEV dev
, INT left
, INT top
, INT right
, INT bottom
,
925 INT ell_width
, INT ell_height
)
927 struct windrv_physdev
*physdev
= get_windrv_physdev( dev
);
930 lock_surface( physdev
->surface
);
931 dev
= GET_NEXT_PHYSDEV( dev
, pRoundRect
);
932 ret
= dev
->funcs
->pRoundRect( dev
, left
, top
, right
, bottom
, ell_width
, ell_height
);
933 unlock_surface( physdev
->surface
);
937 static UINT
windrv_SetBoundsRect( PHYSDEV dev
, RECT
*rect
, UINT flags
)
939 /* do nothing, we use the dibdrv bounds tracking for our own purpose */
943 static INT
windrv_SetDIBitsToDevice( PHYSDEV dev
, INT x_dst
, INT y_dst
, DWORD cx
, DWORD cy
,
944 INT x_src
, INT y_src
, UINT startscan
, UINT lines
,
945 const void *bits
, BITMAPINFO
*src_info
, UINT coloruse
)
947 struct windrv_physdev
*physdev
= get_windrv_physdev( dev
);
950 lock_surface( physdev
->surface
);
951 dev
= GET_NEXT_PHYSDEV( dev
, pSetDIBitsToDevice
);
952 ret
= dev
->funcs
->pSetDIBitsToDevice( dev
, x_dst
, y_dst
, cx
, cy
,
953 x_src
, y_src
, startscan
, lines
, bits
, src_info
, coloruse
);
954 unlock_surface( physdev
->surface
);
958 static void windrv_SetDeviceClipping( PHYSDEV dev
, HRGN rgn
)
960 dev
= GET_NEXT_PHYSDEV( dev
, pSetDeviceClipping
);
961 dev
->funcs
->pSetDeviceClipping( dev
, rgn
);
962 /* also forward to the graphics driver for the OpenGL case */
963 if (dev
->funcs
== &dib_driver
)
965 dev
= GET_NEXT_PHYSDEV( dev
, pSetDeviceClipping
);
966 dev
->funcs
->pSetDeviceClipping( dev
, rgn
);
970 static COLORREF
windrv_SetPixel( PHYSDEV dev
, INT x
, INT y
, COLORREF color
)
972 struct windrv_physdev
*physdev
= get_windrv_physdev( dev
);
975 lock_surface( physdev
->surface
);
976 dev
= GET_NEXT_PHYSDEV( dev
, pSetPixel
);
977 ret
= dev
->funcs
->pSetPixel( dev
, x
, y
, color
);
978 unlock_surface( physdev
->surface
);
982 static BOOL
windrv_StretchBlt( PHYSDEV dst_dev
, struct bitblt_coords
*dst
,
983 PHYSDEV src_dev
, struct bitblt_coords
*src
, DWORD rop
)
985 struct windrv_physdev
*physdev
= get_windrv_physdev( dst_dev
);
988 lock_surface( physdev
->surface
);
989 dst_dev
= GET_NEXT_PHYSDEV( dst_dev
, pStretchBlt
);
990 ret
= dst_dev
->funcs
->pStretchBlt( dst_dev
, dst
, src_dev
, src
, rop
);
991 unlock_surface( physdev
->surface
);
995 static INT
windrv_StretchDIBits( PHYSDEV dev
, INT x_dst
, INT y_dst
, INT width_dst
, INT height_dst
,
996 INT x_src
, INT y_src
, INT width_src
, INT height_src
, const void *bits
,
997 BITMAPINFO
*src_info
, UINT coloruse
, DWORD rop
)
999 struct windrv_physdev
*physdev
= get_windrv_physdev( dev
);
1002 lock_surface( physdev
->surface
);
1003 dev
= GET_NEXT_PHYSDEV( dev
, pStretchDIBits
);
1004 ret
= dev
->funcs
->pStretchDIBits( dev
, x_dst
, y_dst
, width_dst
, height_dst
,
1005 x_src
, y_src
, width_src
, height_src
, bits
, src_info
, coloruse
, rop
);
1006 unlock_surface( physdev
->surface
);
1010 static struct opengl_funcs
*windrv_wine_get_wgl_driver( PHYSDEV dev
, UINT version
)
1012 dev
= GET_NEXT_PHYSDEV( dev
, wine_get_wgl_driver
);
1013 if (dev
->funcs
== &dib_driver
) dev
= GET_NEXT_PHYSDEV( dev
, wine_get_wgl_driver
);
1014 return dev
->funcs
->wine_get_wgl_driver( dev
, version
);
1017 static const struct gdi_dc_funcs window_driver
=
1019 NULL
, /* pAbortDoc */
1020 NULL
, /* pAbortPath */
1021 windrv_AlphaBlend
, /* pAlphaBlend */
1022 NULL
, /* pAngleArc */
1023 windrv_Arc
, /* pArc */
1024 windrv_ArcTo
, /* pArcTo */
1025 NULL
, /* pBeginPath */
1026 windrv_BlendImage
, /* pBlendImage */
1027 windrv_Chord
, /* pChord */
1028 NULL
, /* pCloseFigure */
1029 NULL
, /* pCreateCompatibleDC */
1030 windrv_CreateDC
, /* pCreateDC */
1031 windrv_DeleteDC
, /* pDeleteDC */
1032 NULL
, /* pDeleteObject */
1033 NULL
, /* pDeviceCapabilities */
1034 windrv_Ellipse
, /* pEllipse */
1036 NULL
, /* pEndPage */
1037 NULL
, /* pEndPath */
1038 NULL
, /* pEnumFonts */
1039 NULL
, /* pEnumICMProfiles */
1040 NULL
, /* pExcludeClipRect */
1041 NULL
, /* pExtDeviceMode */
1042 NULL
, /* pExtEscape */
1043 windrv_ExtFloodFill
, /* pExtFloodFill */
1044 NULL
, /* pExtSelectClipRgn */
1045 windrv_ExtTextOut
, /* pExtTextOut */
1046 NULL
, /* pFillPath */
1047 NULL
, /* pFillRgn */
1048 NULL
, /* pFlattenPath */
1049 NULL
, /* pFontIsLinked */
1050 NULL
, /* pFrameRgn */
1051 NULL
, /* pGdiComment */
1052 NULL
, /* pGdiRealizationInfo */
1053 NULL
, /* pGetBoundsRect */
1054 NULL
, /* pGetCharABCWidths */
1055 NULL
, /* pGetCharABCWidthsI */
1056 NULL
, /* pGetCharWidth */
1057 NULL
, /* pGetDeviceCaps */
1058 NULL
, /* pGetDeviceGammaRamp */
1059 NULL
, /* pGetFontData */
1060 NULL
, /* pGetFontUnicodeRanges */
1061 NULL
, /* pGetGlyphIndices */
1062 NULL
, /* pGetGlyphOutline */
1063 NULL
, /* pGetICMProfile */
1064 windrv_GetImage
, /* pGetImage */
1065 NULL
, /* pGetKerningPairs */
1066 NULL
, /* pGetNearestColor */
1067 NULL
, /* pGetOutlineTextMetrics */
1068 windrv_GetPixel
, /* pGetPixel */
1069 NULL
, /* pGetSystemPaletteEntries */
1070 NULL
, /* pGetTextCharsetInfo */
1071 NULL
, /* pGetTextExtentExPoint */
1072 NULL
, /* pGetTextExtentExPointI */
1073 NULL
, /* pGetTextFace */
1074 NULL
, /* pGetTextMetrics */
1075 windrv_GradientFill
, /* pGradientFill */
1076 NULL
, /* pIntersectClipRect */
1077 NULL
, /* pInvertRgn */
1078 windrv_LineTo
, /* pLineTo */
1079 NULL
, /* pModifyWorldTransform */
1081 NULL
, /* pOffsetClipRgn */
1082 NULL
, /* pOffsetViewportOrg */
1083 NULL
, /* pOffsetWindowOrg */
1084 windrv_PaintRgn
, /* pPaintRgn */
1085 windrv_PatBlt
, /* pPatBlt */
1086 windrv_Pie
, /* pPie */
1087 NULL
, /* pPolyBezier */
1088 NULL
, /* pPolyBezierTo */
1089 NULL
, /* pPolyDraw */
1090 windrv_PolyPolygon
, /* pPolyPolygon */
1091 windrv_PolyPolyline
, /* pPolyPolyline */
1092 windrv_Polygon
, /* pPolygon */
1093 windrv_Polyline
, /* pPolyline */
1094 NULL
, /* pPolylineTo */
1095 windrv_PutImage
, /* pPutImage */
1096 NULL
, /* pRealizeDefaultPalette */
1097 NULL
, /* pRealizePalette */
1098 windrv_Rectangle
, /* pRectangle */
1099 NULL
, /* pResetDC */
1100 NULL
, /* pRestoreDC */
1101 windrv_RoundRect
, /* pRoundRect */
1103 NULL
, /* pScaleViewportExt */
1104 NULL
, /* pScaleWindowExt */
1105 NULL
, /* pSelectBitmap */
1106 NULL
, /* pSelectBrush */
1107 NULL
, /* pSelectClipPath */
1108 NULL
, /* pSelectFont */
1109 NULL
, /* pSelectPalette */
1110 NULL
, /* pSelectPen */
1111 NULL
, /* pSetArcDirection */
1112 NULL
, /* pSetBkColor */
1113 NULL
, /* pSetBkMode */
1114 windrv_SetBoundsRect
, /* pSetBoundsRect */
1115 NULL
, /* pSetDCBrushColor */
1116 NULL
, /* pSetDCPenColor */
1117 windrv_SetDIBitsToDevice
, /* pSetDIBitsToDevice */
1118 windrv_SetDeviceClipping
, /* pSetDeviceClipping */
1119 NULL
, /* pSetDeviceGammaRamp */
1120 NULL
, /* pSetLayout */
1121 NULL
, /* pSetMapMode */
1122 NULL
, /* pSetMapperFlags */
1123 windrv_SetPixel
, /* pSetPixel */
1124 NULL
, /* pSetPolyFillMode */
1125 NULL
, /* pSetROP2 */
1126 NULL
, /* pSetRelAbs */
1127 NULL
, /* pSetStretchBltMode */
1128 NULL
, /* pSetTextAlign */
1129 NULL
, /* pSetTextCharacterExtra */
1130 NULL
, /* pSetTextColor */
1131 NULL
, /* pSetTextJustification */
1132 NULL
, /* pSetViewportExt */
1133 NULL
, /* pSetViewportOrg */
1134 NULL
, /* pSetWindowExt */
1135 NULL
, /* pSetWindowOrg */
1136 NULL
, /* pSetWorldTransform */
1137 NULL
, /* pStartDoc */
1138 NULL
, /* pStartPage */
1139 windrv_StretchBlt
, /* pStretchBlt */
1140 windrv_StretchDIBits
, /* pStretchDIBits */
1141 NULL
, /* pStrokeAndFillPath */
1142 NULL
, /* pStrokePath */
1143 NULL
, /* pUnrealizePalette */
1144 NULL
, /* pWidenPath */
1145 windrv_wine_get_wgl_driver
, /* wine_get_wgl_driver */
1146 GDI_PRIORITY_DIB_DRV
+ 10 /* priority */