1/* 2 * Copyright © 2009 Maarten Maathuis 3 * Copyright 2011 VMWare, Inc. All Rights Reserved. 4 * 5 * Permission is hereby granted, free of charge, to any person obtaining a 6 * copy of this software and associated documentation files (the 7 * "Software"), to deal in the Software without restriction, including 8 * without limitation the rights to use, copy, modify, merge, publish, 9 * distribute, sub license, and/or sell copies of the Software, and to 10 * permit persons to whom the Software is furnished to do so, subject to 11 * the following conditions: 12 * 13 * The above copyright notice and this permission notice (including the 14 * next paragraph) shall be included in all copies or substantial portions 15 * of the Software. 16 * 17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 18 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 19 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. 20 * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR 21 * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 22 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 23 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 24 * 25 * Author: Based on "exa_driver.c" 26 * Author: Thomas Hellstrom <thellstrom@vmware.com> 27 */ 28 29#include "saa_priv.h" 30#include "saa.h" 31 32PixmapPtr 33saa_create_pixmap(ScreenPtr pScreen, int w, int h, int depth, 34 unsigned usage_hint) 35{ 36 PixmapPtr pPixmap; 37 struct saa_pixmap *spix; 38 int bpp; 39 size_t paddedWidth; 40 struct saa_screen_priv *sscreen = saa_screen(pScreen); 41 int new_pitch = 0; 42 struct saa_driver *driver = sscreen->driver; 43 44 if (w > 32767 || h > 32767) 45 return NullPixmap; 46 47 /* 48 * Create a scratch pixmap without backing storage (w and h are zero) 49 */ 50 51 saa_swap(sscreen, pScreen, CreatePixmap); 52 pPixmap = pScreen->CreatePixmap(pScreen, 0, 0, depth, usage_hint); 53 saa_swap(sscreen, pScreen, CreatePixmap); 54 55 if (!pPixmap) 56 goto out_no_pix; 57 58 spix = saa_pixmap(pPixmap); 59 memset(spix, 0, driver->pixmap_size); 60 REGION_NULL(pScreen, &spix->dirty_shadow); 61 REGION_NULL(pScreen, &spix->dirty_hw); 62 REGION_NULL(pScreen, &spix->shadow_damage); 63 spix->read_access = 0; 64 spix->write_access = 0; 65 spix->mapped_access = 0; 66 spix->addr = NULL; 67 spix->auth_loc = saa_loc_override; 68 spix->override = SAA_INVALID_ADDRESS; 69 spix->pixmap = pPixmap; 70 bpp = pPixmap->drawable.bitsPerPixel; 71 72 if (!driver->create_pixmap(driver, spix, w, h, depth, 73 usage_hint, bpp, &new_pitch)) 74 goto out_no_driver_priv; 75 76 paddedWidth = new_pitch; 77 spix->damage = NULL; 78 79 /* 80 * Now set w and h to the correct value. This might allocate 81 * backing store if w and h are NON-NULL. 82 */ 83 84 if (!(*pScreen->ModifyPixmapHeader) (pPixmap, w, h, 0, 0, 85 paddedWidth, NULL)) 86 goto out_no_pixmap_header; 87 88 /* 89 * During a fallback we must prepare access. This hack is initially used 90 * for pixmaps created during ValidateGC. 91 */ 92 93 spix->fallback_created = FALSE; 94 if (sscreen->fallback_count) { 95 if (!saa_prepare_access_pixmap(pPixmap, SAA_ACCESS_W, NULL)) 96 goto out_no_access; 97 98 spix->fallback_created = TRUE; 99 } 100 101 return pPixmap; 102 out_no_access: 103 out_no_pixmap_header: 104 driver->destroy_pixmap(driver, pPixmap); 105 out_no_driver_priv: 106 saa_swap(sscreen, pScreen, DestroyPixmap); 107 pScreen->DestroyPixmap(pPixmap); 108 saa_swap(sscreen, pScreen, DestroyPixmap); 109 out_no_pix: 110 LogMessage(X_ERROR, "Failing pixmap creation.\n"); 111 return NullPixmap; 112} 113 114Bool 115saa_destroy_pixmap(PixmapPtr pPixmap) 116{ 117 ScreenPtr pScreen = pPixmap->drawable.pScreen; 118 struct saa_screen_priv *sscreen = saa_screen(pScreen); 119 Bool ret; 120 struct saa_driver *driver = sscreen->driver; 121 122 if (pPixmap->refcnt == 1) { 123 struct saa_pixmap *spix = saa_pixmap(pPixmap); 124 125 if (spix->fallback_created) { 126 if (!sscreen->fallback_count) 127 LogMessage(X_ERROR, "Fallback pixmap destroyed outside " 128 "fallback.\n"); 129 130 saa_finish_access_pixmap(pPixmap, SAA_ACCESS_W); 131 } 132 133 driver->destroy_pixmap(driver, pPixmap); 134 135 REGION_UNINIT(pScreen, &spix->dirty_hw); 136 REGION_UNINIT(pScreen, &spix->dirty_shadow); 137 if (spix->damage) 138 DamageDestroy(spix->damage); 139 } 140 141 saa_swap(sscreen, pScreen, DestroyPixmap); 142 ret = pScreen->DestroyPixmap(pPixmap); 143 saa_swap(sscreen, pScreen, DestroyPixmap); 144 145 return ret; 146} 147 148Bool 149saa_modify_pixmap_header(PixmapPtr pPixmap, int width, int height, int depth, 150 int bitsPerPixel, int devKind, pointer pPixData) 151{ 152 ScreenPtr pScreen; 153 struct saa_screen_priv *sscreen; 154 struct saa_pixmap *spix; 155 struct saa_driver *driver; 156 Bool ret = TRUE; 157 158 if (!pPixmap) 159 return FALSE; 160 161 pScreen = pPixmap->drawable.pScreen; 162 sscreen = saa_screen(pScreen); 163 spix = saa_pixmap(pPixmap); 164 driver = sscreen->driver; 165 166 if (spix && driver->modify_pixmap_header && 167 driver->modify_pixmap_header(pPixmap, width, height, depth, 168 bitsPerPixel, devKind, pPixData)) { 169 spix->auth_loc = saa_loc_driver; 170 spix->override = SAA_INVALID_ADDRESS; 171 goto out; 172 } 173 174 saa_swap(sscreen, pScreen, ModifyPixmapHeader); 175 ret = pScreen->ModifyPixmapHeader(pPixmap, width, height, depth, 176 bitsPerPixel, devKind, pPixData); 177 saa_swap(sscreen, pScreen, ModifyPixmapHeader); 178 spix->override = pPixmap->devPrivate.ptr; 179 spix->auth_loc = saa_loc_override; 180 181 out: 182 pPixmap->devPrivate.ptr = NULL; 183 return ret; 184} 185 186struct saa_pixmap * 187saa_get_saa_pixmap(PixmapPtr pPixmap) 188{ 189 return saa_pixmap(pPixmap); 190} 191 192void 193saa_pixmap_dirty(PixmapPtr pixmap, Bool hw, RegionPtr reg) 194{ 195 struct saa_pixmap *spix = saa_pixmap(pixmap); 196 struct saa_screen_priv *sscreen = saa_screen(pixmap->drawable.pScreen); 197 198 if (hw) { 199 REGION_UNION(pixmap->drawable.pScreen, &spix->dirty_hw, 200 &spix->dirty_hw, reg); 201 REGION_SUBTRACT(pixmap->drawable.pScreen, &spix->dirty_shadow, 202 &spix->dirty_shadow, reg); 203 } else { 204 REGION_UNION(pixmap->drawable.pScreen, &spix->dirty_shadow, 205 &spix->dirty_shadow, reg); 206 REGION_SUBTRACT(pixmap->drawable.pScreen, &spix->dirty_hw, 207 &spix->dirty_hw, reg); 208 } 209 210 sscreen->driver->damage(sscreen->driver, pixmap, hw, reg); 211} 212 213void 214saa_drawable_dirty(DrawablePtr draw, Bool hw, RegionPtr reg) 215{ 216 PixmapPtr pixmap; 217 int x_offset, y_offset; 218 219 pixmap = saa_get_pixmap(draw, &x_offset, &y_offset); 220 REGION_TRANSLATE(draw->pScreen, reg, x_offset, y_offset); 221 saa_pixmap_dirty(pixmap, hw, reg); 222 REGION_TRANSLATE(draw->pScreen, reg, -x_offset, -y_offset); 223} 224