First import
[xorg_rtime.git] / xorg-server-1.4 / hw / xgl / xglpixmap.c
blob368c3eaebabce107808691b39453d028789d8edd
1 /*
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
13 * implied warranty.
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>
26 #include "xgl.h"
27 #include "fb.h"
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])
47 static void
48 xglPixmapDamageReport (DamagePtr pDamage,
49 RegionPtr pRegion,
50 void *closure)
52 PixmapPtr pPixmap = (PixmapPtr) closure;
53 BoxPtr pExt;
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;
73 else
74 pPixmapPriv->damageBox = *pExt;
78 static Bool
79 xglPixmapCreateDamage (PixmapPtr pPixmap)
81 XGL_PIXMAP_PRIV (pPixmap);
83 pPixmapPriv->pDamage =
84 DamageCreate (xglPixmapDamageReport, (DamageDestroyFunc) 0,
85 DamageReportRawRegion, TRUE,
86 pPixmap->drawable.pScreen,
87 (void *) pPixmap);
88 if (!pPixmapPriv->pDamage)
89 return FALSE;
91 DamageRegister (&pPixmap->drawable, pPixmapPriv->pDamage);
93 return TRUE;
96 void
97 xglSetPixmapVisual (PixmapPtr pPixmap,
98 xglVisualPtr pVisual)
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;
112 if (surface)
114 glitz_drawable_t *drawable;
116 drawable = glitz_surface_get_attached_drawable (surface);
117 if (drawable)
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;
136 else if (pOldVisual)
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);
159 static Bool
160 xglPixmapSurfaceInit (PixmapPtr pPixmap,
161 unsigned long features,
162 int width,
163 int height)
165 BoxRec box;
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;
175 box.x1 = 0;
176 box.y1 = 0;
177 box.x2 = width;
178 box.y2 = height;
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);
203 if (width && height)
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;
218 return TRUE;
221 PixmapPtr
222 xglCreatePixmap (ScreenPtr pScreen,
223 int width,
224 int height,
225 int depth)
227 xglPixmapPtr pPixmapPriv;
228 PixmapPtr pPixmap;
230 XGL_SCREEN_PRIV (pScreen);
232 pPixmap = AllocatePixmap (pScreen, 0);
233 if (!pPixmap)
234 return NullPixmap;
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;
248 #ifdef COMPOSITE
249 pPixmap->screen_x = 0;
250 pPixmap->screen_y = 0;
251 #endif
253 pPixmap->devKind = 0;
254 pPixmap->refcnt = 1;
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))
263 return NullPixmap;
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;
273 return pPixmap;
276 void
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);
305 Bool
306 xglDestroyPixmap (PixmapPtr pPixmap)
308 if (--pPixmap->refcnt)
309 return TRUE;
311 xglFiniPixmap (pPixmap);
313 xfree (pPixmap);
315 return TRUE;
318 Bool
319 xglModifyPixmapHeader (PixmapPtr pPixmap,
320 int width,
321 int height,
322 int depth,
323 int bitsPerPixel,
324 int devKind,
325 pointer pPixData)
327 xglScreenPtr pScreenPriv;
328 xglPixmapPtr pPixmapPriv;
329 int oldWidth, oldHeight;
331 if (!pPixmap)
332 return FALSE;
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;
352 pPixmap->refcnt = 1;
354 else
356 if (width > 0)
357 pPixmap->drawable.width = width;
359 if (height > 0)
360 pPixmap->drawable.height = height;
362 if (depth > 0)
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);
370 if (devKind > 0)
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))
395 return FALSE;
398 if (pPixData)
400 BoxRec box;
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)
425 return FALSE;
427 pPixmapPriv->allBits = TRUE;
429 box.x1 = 0;
430 box.y1 = 0;
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,
436 &box, 1);
438 if (pPixmapPriv->pDamage)
440 RegionPtr pRegion;
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);
453 * Screen pixmap
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;
476 return TRUE;
479 RegionPtr
480 xglPixmapToRegion (PixmapPtr pPixmap)
482 ScreenPtr pScreen = pPixmap->drawable.pScreen;
483 RegionPtr pRegion;
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);
494 return pRegion;
497 xglGeometryPtr
498 xglPixmapToGeometry (PixmapPtr pPixmap,
499 int xOff,
500 int yOff)
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))
515 return NULL;
518 pGeometry = xalloc (sizeof (xglGeometryRec));
519 if (!pGeometry)
520 return NULL;
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;
534 else
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) *
542 sizeof (FbBits);
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;
555 Bool
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)
565 return FALSE;
567 pPixmapPriv->surface =
568 glitz_surface_create (pScreenPriv->drawable,
569 pPixmapPriv->pVisual->format.surface,
570 pPixmap->drawable.width,
571 pPixmap->drawable.height,
572 0, NULL);
573 if (!pPixmapPriv->surface)
575 pPixmapPriv->pVisual = NULL;
576 pPixmapPriv->target = xglPixmapTargetNo;
578 return FALSE;
582 return TRUE;
585 Bool
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);
599 if (stride)
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));
609 else
611 pPixmapPriv->bits = xalloc (height * stride);
612 if (!pPixmapPriv->bits)
613 return FALSE;
615 buffer = glitz_buffer_create_for_data (pPixmapPriv->bits);
618 if (!buffer)
620 if (pPixmapPriv->bits)
621 xfree (pPixmapPriv->bits);
622 pPixmapPriv->bits = NULL;
623 return FALSE;
625 pPixmapPriv->buffer = buffer;
628 if (pScreenPriv->yInverted)
629 pPixmapPriv->stride = stride;
630 else
631 pPixmapPriv->stride = -stride;
633 return TRUE;
636 Bool
637 xglMapPixmapBits (PixmapPtr pPixmap)
639 if (!pPixmap->devPrivate.ptr)
641 CARD8 *bits;
643 XGL_PIXMAP_PRIV (pPixmap);
645 if (!pPixmapPriv->buffer)
646 if (!xglAllocatePixmapBits (pPixmap,
647 XGL_PIXMAP_USAGE_HINT_DEFAULT))
648 return FALSE;
650 bits = glitz_buffer_map (pPixmapPriv->buffer,
651 GLITZ_BUFFER_ACCESS_READ_WRITE);
652 if (!bits)
653 return FALSE;
655 pPixmap->devKind = pPixmapPriv->stride;
656 if (pPixmapPriv->stride < 0)
658 pPixmap->devPrivate.ptr = bits +
659 (pPixmap->drawable.height - 1) * -pPixmapPriv->stride;
661 else
663 pPixmap->devPrivate.ptr = bits;
667 return TRUE;
670 Bool
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))
680 return FALSE;
682 return TRUE;
685 Bool
686 xglCheckPixmapSize (PixmapPtr pPixmap,
687 xglSizeConstraintPtr pSize)
689 if (pPixmap->drawable.width < pSize->minWidth ||
690 pPixmap->drawable.height < pSize->minHeight)
691 return FALSE;
693 if (pPixmap->drawable.width > pSize->aboveWidth ||
694 pPixmap->drawable.height > pSize->aboveHeight)
695 return TRUE;
697 return FALSE;
700 void
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))
709 xglVisualPtr v;
711 if (pAccel->pbuffer)
713 for (v = pScreenPriv->pVisual; v; v = v->next)
715 if (v->pPixel->depth != pPixmap->drawable.depth)
716 continue;
718 if (v->format.drawable && v->pbuffer)
719 break;
722 else
724 for (v = pScreenPriv->pVisual; v; v = v->next)
726 if (v->pPixel->depth != pPixmap->drawable.depth)
727 continue;
729 if (v->format.drawable && !v->pbuffer)
730 break;
734 if (v)
736 xglSetPixmapVisual (pPixmap, v);
737 if (!pPixmapPriv->target)
738 pPixmapPriv->target = xglPixmapTargetOut;