2 * Copyright © 2004 David Reveman
4 * Permission to use, copy, modify, distribute, and sell this software
5 * and its documentation for any purpose is hereby granted without
6 * fee, provided that the above copyright notice appear in all copies
7 * and that both that copyright notice and this permission notice
8 * appear in supporting documentation, and that the name of
9 * David Reveman not be used in advertising or publicity pertaining to
10 * distribution of the software without specific, written prior permission.
11 * David Reveman makes no representations about the suitability of this
12 * software for any purpose. It is provided "as is" without express or
15 * DAVID REVEMAN DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
16 * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN
17 * NO EVENT SHALL DAVID REVEMAN BE LIABLE FOR ANY SPECIAL, INDIRECT OR
18 * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
19 * OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
20 * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
21 * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
23 * Author: David Reveman <davidr@novell.com>
29 static glitz_buffer_hint_t xglPixmapUsageHints
[] = {
30 (glitz_buffer_hint_t
) 0, /* reserved for system memory */
31 GLITZ_BUFFER_HINT_STREAM_DRAW
,
32 GLITZ_BUFFER_HINT_STREAM_READ
,
33 GLITZ_BUFFER_HINT_STREAM_COPY
,
34 GLITZ_BUFFER_HINT_STATIC_DRAW
,
35 GLITZ_BUFFER_HINT_STATIC_READ
,
36 GLITZ_BUFFER_HINT_STATIC_COPY
,
37 GLITZ_BUFFER_HINT_DYNAMIC_DRAW
,
38 GLITZ_BUFFER_HINT_DYNAMIC_READ
,
39 GLITZ_BUFFER_HINT_DYNAMIC_COPY
42 #define NUM_XGL_PIXMAP_USAGE_HINTS \
43 (sizeof (xglPixmapUsageHints) / sizeof (xglPixmapUsageHints[0]))
45 #define XGL_PIXMAP_USAGE_HINT(hint) (xglPixmapUsageHints[hint])
48 xglPixmapDamageReport (DamagePtr pDamage
,
52 PixmapPtr pPixmap
= (PixmapPtr
) closure
;
55 XGL_PIXMAP_PRIV (pPixmap
);
57 pExt
= REGION_EXTENTS (pPixmap
->drawable
.pScreen
, pRegion
);
59 if (BOX_NOTEMPTY (&pPixmapPriv
->damageBox
))
61 if (pExt
->x1
< pPixmapPriv
->damageBox
.x1
)
62 pPixmapPriv
->damageBox
.x1
= pExt
->x1
;
64 if (pExt
->y1
< pPixmapPriv
->damageBox
.y1
)
65 pPixmapPriv
->damageBox
.y1
= pExt
->y1
;
67 if (pExt
->x2
> pPixmapPriv
->damageBox
.x2
)
68 pPixmapPriv
->damageBox
.x2
= pExt
->x2
;
70 if (pExt
->y2
> pPixmapPriv
->damageBox
.y2
)
71 pPixmapPriv
->damageBox
.y2
= pExt
->y2
;
74 pPixmapPriv
->damageBox
= *pExt
;
79 xglPixmapCreateDamage (PixmapPtr pPixmap
)
81 XGL_PIXMAP_PRIV (pPixmap
);
83 pPixmapPriv
->pDamage
=
84 DamageCreate (xglPixmapDamageReport
, (DamageDestroyFunc
) 0,
85 DamageReportRawRegion
, TRUE
,
86 pPixmap
->drawable
.pScreen
,
88 if (!pPixmapPriv
->pDamage
)
91 DamageRegister (&pPixmap
->drawable
, pPixmapPriv
->pDamage
);
97 xglSetPixmapVisual (PixmapPtr pPixmap
,
100 xglVisualPtr pOldVisual
;
102 XGL_PIXMAP_PRIV (pPixmap
);
104 pOldVisual
= pPixmapPriv
->pVisual
;
105 if (pOldVisual
&& pVisual
)
107 glitz_surface_t
*surface
;
109 if (pOldVisual
->vid
!= pVisual
->vid
)
111 surface
= pPixmapPriv
->surface
;
114 glitz_drawable_t
*drawable
;
116 drawable
= glitz_surface_get_attached_drawable (surface
);
119 if (pOldVisual
->format
.drawable
->id
!=
120 pVisual
->format
.drawable
->id
)
122 glitz_surface_detach (pPixmapPriv
->surface
);
123 pPixmapPriv
->target
= xglPixmapTargetOut
;
127 if (pOldVisual
->format
.surface
->id
!= pVisual
->format
.surface
->id
)
129 xglSyncBits (&pPixmap
->drawable
, NULL
);
130 glitz_surface_destroy (pPixmapPriv
->surface
);
131 pPixmapPriv
->surface
= 0;
138 if (pPixmapPriv
->surface
)
140 xglSyncBits (&pPixmap
->drawable
, NULL
);
141 glitz_surface_destroy (pPixmapPriv
->surface
);
142 pPixmapPriv
->surface
= 0;
144 pPixmapPriv
->target
= xglPixmapTargetNo
;
147 pPixmapPriv
->pVisual
= pVisual
;
149 if (pPixmapPriv
->pVisual
&& pPixmapPriv
->pVisual
->format
.surface
)
151 if (!pPixmapPriv
->pDamage
)
153 if (!xglPixmapCreateDamage (pPixmap
))
154 FatalError (XGL_SW_FAILURE_STRING
);
160 xglPixmapSurfaceInit (PixmapPtr pPixmap
,
161 unsigned long features
,
167 XGL_PIXMAP_PRIV (pPixmap
);
169 pPixmapPriv
->surface
= NULL
;
170 pPixmapPriv
->drawable
= NULL
;
171 pPixmapPriv
->acceleratedTile
= FALSE
;
172 pPixmapPriv
->pictureMask
= ~0;
173 pPixmapPriv
->target
= xglPixmapTargetNo
;
180 REGION_INIT (pScreen
, &pPixmapPriv
->bitRegion
, &box
, 1);
182 pPixmapPriv
->pVisual
= xglFindVisualWithDepth (pPixmap
->drawable
.pScreen
,
183 pPixmap
->drawable
.depth
);
184 if (pPixmapPriv
->pVisual
)
186 XGL_SCREEN_PRIV (pPixmap
->drawable
.pScreen
);
188 /* general pixmap acceleration */
189 if (pPixmapPriv
->pVisual
->format
.drawable
&&
190 pScreenPriv
->accel
.pixmap
.enabled
&&
191 xglCheckPixmapSize (pPixmap
, &pScreenPriv
->accel
.pixmap
.size
))
192 pPixmapPriv
->target
= xglPixmapTargetOut
;
195 if (pPixmapPriv
->pVisual
&& pPixmapPriv
->pVisual
->format
.surface
)
197 if (!pPixmapPriv
->pDamage
)
199 if (!xglPixmapCreateDamage (pPixmap
))
200 FatalError (XGL_SW_FAILURE_STRING
);
205 if (width
== 1 && height
== 1)
207 pPixmapPriv
->acceleratedTile
= TRUE
;
209 else if (features
& GLITZ_FEATURE_TEXTURE_BORDER_CLAMP_MASK
)
211 if ((features
& GLITZ_FEATURE_TEXTURE_NON_POWER_OF_TWO_MASK
) ||
212 (POWER_OF_TWO (width
) && POWER_OF_TWO (height
)))
213 pPixmapPriv
->acceleratedTile
= TRUE
;
222 xglCreatePixmap (ScreenPtr pScreen
,
227 xglPixmapPtr pPixmapPriv
;
230 XGL_SCREEN_PRIV (pScreen
);
232 pPixmap
= AllocatePixmap (pScreen
, 0);
236 pPixmap
->drawable
.type
= DRAWABLE_PIXMAP
;
237 pPixmap
->drawable
.class = 0;
238 pPixmap
->drawable
.pScreen
= pScreen
;
239 pPixmap
->drawable
.depth
= depth
;
240 pPixmap
->drawable
.bitsPerPixel
= BitsPerPixel (depth
);
241 pPixmap
->drawable
.id
= 0;
242 pPixmap
->drawable
.serialNumber
= NEXT_SERIAL_NUMBER
;
243 pPixmap
->drawable
.x
= 0;
244 pPixmap
->drawable
.y
= 0;
245 pPixmap
->drawable
.width
= width
;
246 pPixmap
->drawable
.height
= height
;
249 pPixmap
->screen_x
= 0;
250 pPixmap
->screen_y
= 0;
253 pPixmap
->devKind
= 0;
255 pPixmap
->devPrivate
.ptr
= 0;
257 pPixmapPriv
= XGL_GET_PIXMAP_PRIV (pPixmap
);
259 pPixmapPriv
->pVisual
= NULL
;
260 pPixmapPriv
->pDamage
= NULL
;
262 if (!xglPixmapSurfaceInit (pPixmap
, pScreenPriv
->features
, width
, height
))
265 pPixmapPriv
->buffer
= NULL
;
266 pPixmapPriv
->bits
= (pointer
) 0;
267 pPixmapPriv
->stride
= 0;
268 pPixmapPriv
->pGeometry
= NULL
;
269 pPixmapPriv
->allBits
= TRUE
;
271 pPixmapPriv
->damageBox
= miEmptyBox
;
277 xglFiniPixmap (PixmapPtr pPixmap
)
279 XGL_PIXMAP_PRIV (pPixmap
);
281 if (pPixmap
->devPrivate
.ptr
)
283 if (pPixmapPriv
->buffer
)
284 glitz_buffer_unmap (pPixmapPriv
->buffer
);
287 if (pPixmapPriv
->pGeometry
)
288 GEOMETRY_UNINIT (pPixmapPriv
->pGeometry
);
290 if (pPixmapPriv
->buffer
)
291 glitz_buffer_destroy (pPixmapPriv
->buffer
);
293 if (pPixmapPriv
->bits
)
294 xfree (pPixmapPriv
->bits
);
296 REGION_UNINIT (pPixmap
->drawable
.pScreen
, &pPixmapPriv
->bitRegion
);
298 if (pPixmapPriv
->drawable
)
299 glitz_drawable_destroy (pPixmapPriv
->drawable
);
301 if (pPixmapPriv
->surface
)
302 glitz_surface_destroy (pPixmapPriv
->surface
);
306 xglDestroyPixmap (PixmapPtr pPixmap
)
308 if (--pPixmap
->refcnt
)
311 xglFiniPixmap (pPixmap
);
319 xglModifyPixmapHeader (PixmapPtr pPixmap
,
327 xglScreenPtr pScreenPriv
;
328 xglPixmapPtr pPixmapPriv
;
329 int oldWidth
, oldHeight
;
334 pScreenPriv
= XGL_GET_SCREEN_PRIV (pPixmap
->drawable
.pScreen
);
335 pPixmapPriv
= XGL_GET_PIXMAP_PRIV (pPixmap
);
337 oldWidth
= pPixmap
->drawable
.width
;
338 oldHeight
= pPixmap
->drawable
.height
;
340 if ((width
> 0) && (height
> 0) && (depth
> 0) && (bitsPerPixel
> 0) &&
341 (devKind
> 0) && pPixData
)
343 pPixmap
->drawable
.depth
= depth
;
344 pPixmap
->drawable
.bitsPerPixel
= bitsPerPixel
;
345 pPixmap
->drawable
.id
= 0;
346 pPixmap
->drawable
.serialNumber
= NEXT_SERIAL_NUMBER
;
347 pPixmap
->drawable
.x
= 0;
348 pPixmap
->drawable
.y
= 0;
349 pPixmap
->drawable
.width
= width
;
350 pPixmap
->drawable
.height
= height
;
351 pPixmapPriv
->stride
= devKind
;
357 pPixmap
->drawable
.width
= width
;
360 pPixmap
->drawable
.height
= height
;
363 pPixmap
->drawable
.depth
= depth
;
365 if (bitsPerPixel
> 0)
366 pPixmap
->drawable
.bitsPerPixel
= bitsPerPixel
;
367 else if ((bitsPerPixel
< 0) && (depth
> 0))
368 pPixmap
->drawable
.bitsPerPixel
= BitsPerPixel (depth
);
371 pPixmapPriv
->stride
= devKind
;
372 else if ((devKind
< 0) && ((width
> 0) || (depth
> 0)))
373 pPixmapPriv
->stride
= PixmapBytePad (pPixmap
->drawable
.width
,
374 pPixmap
->drawable
.depth
);
377 if (pPixmap
->drawable
.width
!= oldWidth
||
378 pPixmap
->drawable
.height
!= oldHeight
)
380 pPixmapPriv
->pVisual
= NULL
;
381 pPixmapPriv
->target
= xglPixmapTargetNo
;
383 if (pPixmapPriv
->drawable
)
384 glitz_drawable_destroy (pPixmapPriv
->drawable
);
386 if (pPixmapPriv
->surface
)
387 glitz_surface_destroy (pPixmapPriv
->surface
);
389 REGION_UNINIT (pPixmap
->drawable
.pScreen
, &pPixmapPriv
->bitRegion
);
391 if (!xglPixmapSurfaceInit (pPixmap
,
392 pScreenPriv
->features
,
393 pPixmap
->drawable
.width
,
394 pPixmap
->drawable
.height
))
402 if (pPixmap
->devPrivate
.ptr
)
404 if (pPixmapPriv
->buffer
)
405 glitz_buffer_unmap (pPixmapPriv
->buffer
);
407 pPixmap
->devPrivate
.ptr
= 0;
410 if (pPixmapPriv
->pGeometry
)
412 GEOMETRY_UNINIT (pPixmapPriv
->pGeometry
);
413 pPixmapPriv
->pGeometry
= NULL
;
416 if (pPixmapPriv
->buffer
)
417 glitz_buffer_destroy (pPixmapPriv
->buffer
);
419 if (pPixmapPriv
->bits
)
420 xfree (pPixmapPriv
->bits
);
422 pPixmapPriv
->bits
= (pointer
) 0;
423 pPixmapPriv
->buffer
= glitz_buffer_create_for_data (pPixData
);
424 if (!pPixmapPriv
->buffer
)
427 pPixmapPriv
->allBits
= TRUE
;
431 box
.x2
= pPixmap
->drawable
.width
;
432 box
.y2
= pPixmap
->drawable
.height
;
434 REGION_UNINIT (pPixmap
->drawable
.pScreen
, &pPixmapPriv
->bitRegion
);
435 REGION_INIT (pPixmap
->drawable
.pScreen
, &pPixmapPriv
->bitRegion
,
438 if (pPixmapPriv
->pDamage
)
442 pRegion
= DamageRegion (pPixmapPriv
->pDamage
);
444 REGION_UNINIT (pPixmap
->drawable
.pScreen
, pRegion
);
445 REGION_INIT (pPixmap
->drawable
.pScreen
, pRegion
, NullBox
, 0);
446 REGION_SUBTRACT (pPixmap
->drawable
.pScreen
, pRegion
,
447 &pPixmapPriv
->bitRegion
, pRegion
);
455 if (!pScreenPriv
->pScreenPixmap
|| pScreenPriv
->pScreenPixmap
== pPixmap
)
457 if (!pPixmapPriv
->drawable
)
459 glitz_drawable_reference (pScreenPriv
->drawable
);
460 pPixmapPriv
->drawable
= pScreenPriv
->drawable
;
463 if (!pPixmapPriv
->surface
)
465 glitz_surface_reference (pScreenPriv
->surface
);
466 pPixmapPriv
->surface
= pScreenPriv
->surface
;
469 pPixmapPriv
->pVisual
= pScreenPriv
->rootVisual
;
470 pPixmapPriv
->target
= xglPixmapTargetIn
;
472 if (!pScreenPriv
->pScreenPixmap
)
473 pScreenPriv
->pScreenPixmap
= pPixmap
;
480 xglPixmapToRegion (PixmapPtr pPixmap
)
482 ScreenPtr pScreen
= pPixmap
->drawable
.pScreen
;
485 XGL_SCREEN_PRIV (pScreen
);
487 if (!xglSyncBits (&pPixmap
->drawable
, NullBox
))
488 FatalError (XGL_SW_FAILURE_STRING
);
490 XGL_SCREEN_UNWRAP (BitmapToRegion
);
491 pRegion
= (*pScreen
->BitmapToRegion
) (pPixmap
);
492 XGL_SCREEN_WRAP (BitmapToRegion
, xglPixmapToRegion
);
498 xglPixmapToGeometry (PixmapPtr pPixmap
,
502 XGL_PIXMAP_PRIV (pPixmap
);
504 if (pPixmap
->devPrivate
.ptr
)
505 xglUnmapPixmapBits (pPixmap
);
507 if (!pPixmapPriv
->pGeometry
)
509 xglGeometryPtr pGeometry
;
511 if (!pPixmapPriv
->buffer
)
513 if (!xglAllocatePixmapBits (pPixmap
,
514 XGL_PIXMAP_USAGE_HINT_DEFAULT
))
518 pGeometry
= xalloc (sizeof (xglGeometryRec
));
522 GEOMETRY_INIT (pPixmap
->drawable
.pScreen
, pGeometry
,
523 GLITZ_GEOMETRY_TYPE_BITMAP
,
524 GEOMETRY_USAGE_DYNAMIC
, 0);
526 GEOMETRY_SET_BUFFER (pGeometry
, pPixmapPriv
->buffer
);
528 if (pPixmapPriv
->stride
< 0)
530 pGeometry
->f
.bitmap
.bytes_per_line
= -pPixmapPriv
->stride
;
531 pGeometry
->f
.bitmap
.scanline_order
=
532 GLITZ_PIXEL_SCANLINE_ORDER_BOTTOM_UP
;
536 pGeometry
->f
.bitmap
.bytes_per_line
= pPixmapPriv
->stride
;
537 pGeometry
->f
.bitmap
.scanline_order
=
538 GLITZ_PIXEL_SCANLINE_ORDER_TOP_DOWN
;
541 pGeometry
->f
.bitmap
.pad
= ((1 + FB_MASK
) >> FB_SHIFT
) *
543 pGeometry
->width
= pPixmap
->drawable
.width
;
544 pGeometry
->count
= pPixmap
->drawable
.height
;
546 pPixmapPriv
->pGeometry
= pGeometry
;
549 pPixmapPriv
->pGeometry
->xOff
= xOff
<< 16;
550 pPixmapPriv
->pGeometry
->yOff
= yOff
<< 16;
552 return pPixmapPriv
->pGeometry
;
556 xglCreatePixmapSurface (PixmapPtr pPixmap
)
558 XGL_PIXMAP_PRIV (pPixmap
);
560 if (!pPixmapPriv
->surface
)
562 XGL_SCREEN_PRIV (pPixmap
->drawable
.pScreen
);
564 if (!pPixmapPriv
->pVisual
|| !pPixmapPriv
->pVisual
->format
.surface
)
567 pPixmapPriv
->surface
=
568 glitz_surface_create (pScreenPriv
->drawable
,
569 pPixmapPriv
->pVisual
->format
.surface
,
570 pPixmap
->drawable
.width
,
571 pPixmap
->drawable
.height
,
573 if (!pPixmapPriv
->surface
)
575 pPixmapPriv
->pVisual
= NULL
;
576 pPixmapPriv
->target
= xglPixmapTargetNo
;
586 xglAllocatePixmapBits (PixmapPtr pPixmap
, int hint
)
588 int width
, height
, bpp
, stride
;
590 XGL_PIXMAP_PRIV (pPixmap
);
591 XGL_SCREEN_PRIV (pPixmap
->drawable
.pScreen
);
593 width
= pPixmap
->drawable
.width
;
594 height
= pPixmap
->drawable
.height
;
595 bpp
= pPixmap
->drawable
.bitsPerPixel
;
597 stride
= ((width
* bpp
+ FB_MASK
) >> FB_SHIFT
) * sizeof (FbBits
);
601 glitz_buffer_t
*buffer
;
603 if ((pScreenPriv
->pboMask
& bpp
) && hint
)
605 buffer
= glitz_pixel_buffer_create (pScreenPriv
->drawable
,
606 NULL
, height
* stride
,
607 XGL_PIXMAP_USAGE_HINT (hint
));
611 pPixmapPriv
->bits
= xalloc (height
* stride
);
612 if (!pPixmapPriv
->bits
)
615 buffer
= glitz_buffer_create_for_data (pPixmapPriv
->bits
);
620 if (pPixmapPriv
->bits
)
621 xfree (pPixmapPriv
->bits
);
622 pPixmapPriv
->bits
= NULL
;
625 pPixmapPriv
->buffer
= buffer
;
628 if (pScreenPriv
->yInverted
)
629 pPixmapPriv
->stride
= stride
;
631 pPixmapPriv
->stride
= -stride
;
637 xglMapPixmapBits (PixmapPtr pPixmap
)
639 if (!pPixmap
->devPrivate
.ptr
)
643 XGL_PIXMAP_PRIV (pPixmap
);
645 if (!pPixmapPriv
->buffer
)
646 if (!xglAllocatePixmapBits (pPixmap
,
647 XGL_PIXMAP_USAGE_HINT_DEFAULT
))
650 bits
= glitz_buffer_map (pPixmapPriv
->buffer
,
651 GLITZ_BUFFER_ACCESS_READ_WRITE
);
655 pPixmap
->devKind
= pPixmapPriv
->stride
;
656 if (pPixmapPriv
->stride
< 0)
658 pPixmap
->devPrivate
.ptr
= bits
+
659 (pPixmap
->drawable
.height
- 1) * -pPixmapPriv
->stride
;
663 pPixmap
->devPrivate
.ptr
= bits
;
671 xglUnmapPixmapBits (PixmapPtr pPixmap
)
673 XGL_PIXMAP_PRIV (pPixmap
);
675 pPixmap
->devKind
= 0;
676 pPixmap
->devPrivate
.ptr
= 0;
678 if (pPixmapPriv
->buffer
)
679 if (glitz_buffer_unmap (pPixmapPriv
->buffer
))
686 xglCheckPixmapSize (PixmapPtr pPixmap
,
687 xglSizeConstraintPtr pSize
)
689 if (pPixmap
->drawable
.width
< pSize
->minWidth
||
690 pPixmap
->drawable
.height
< pSize
->minHeight
)
693 if (pPixmap
->drawable
.width
> pSize
->aboveWidth
||
694 pPixmap
->drawable
.height
> pSize
->aboveHeight
)
701 xglEnablePixmapAccel (PixmapPtr pPixmap
,
702 xglAccelInfoPtr pAccel
)
704 XGL_SCREEN_PRIV (pPixmap
->drawable
.pScreen
);
705 XGL_PIXMAP_PRIV (pPixmap
);
707 if (pAccel
->enabled
&& xglCheckPixmapSize (pPixmap
, &pAccel
->size
))
713 for (v
= pScreenPriv
->pVisual
; v
; v
= v
->next
)
715 if (v
->pPixel
->depth
!= pPixmap
->drawable
.depth
)
718 if (v
->format
.drawable
&& v
->pbuffer
)
724 for (v
= pScreenPriv
->pVisual
; v
; v
= v
->next
)
726 if (v
->pPixel
->depth
!= pPixmap
->drawable
.depth
)
729 if (v
->format
.drawable
&& !v
->pbuffer
)
736 xglSetPixmapVisual (pPixmap
, v
);
737 if (!pPixmapPriv
->target
)
738 pPixmapPriv
->target
= xglPixmapTargetOut
;