xorg_exa.c revision f3c7d6ff866cdd96cdd55baee94f58698a9656a3
1/* 2 * Copyright 2008 Tungsten Graphics, Inc., Cedar Park, Texas. 3 * 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 * 26 * Author: Alan Hourihane <alanh@tungstengraphics.com> 27 * Author: Jakob Bornecrantz <wallbraker@gmail.com> 28 * 29 */ 30 31#include "xorg-server.h" 32#include "xf86.h" 33#include "xorg_tracker.h" 34 35#include "pipe/p_format.h" 36#include "pipe/p_context.h" 37#include "pipe/p_state.h" 38#include "pipe/p_inlines.h" 39 40#include "util/u_rect.h" 41 42struct exa_entity 43{ 44 ExaDriverPtr pExa; 45 struct pipe_context *ctx; 46 struct pipe_screen *scrn; 47}; 48 49struct PixmapPriv 50{ 51 int flags; 52 struct pipe_texture *tex; 53 unsigned int color; 54 struct pipe_surface *src_surf; /* for copies */ 55 56 struct pipe_transfer *map_transfer; 57 unsigned map_count; 58}; 59 60/* 61 * Helper functions 62 */ 63 64static void 65exa_get_pipe_format(int depth, enum pipe_format *format, int *bbp) 66{ 67 switch (depth) { 68 case 32: 69 *format = PIPE_FORMAT_A8R8G8B8_UNORM; 70 assert(*bbp == 32); 71 break; 72 case 24: 73 *format = PIPE_FORMAT_X8R8G8B8_UNORM; 74 assert(*bbp == 32); 75 break; 76 case 16: 77 *format = PIPE_FORMAT_R5G6B5_UNORM; 78 assert(*bbp == 16); 79 break; 80 case 15: 81 *format = PIPE_FORMAT_A1R5G5B5_UNORM; 82 assert(*bbp == 16); 83 break; 84 case 8: 85 case 4: 86 case 1: 87 *format = PIPE_FORMAT_A8R8G8B8_UNORM; /* bad bad bad */ 88 break; 89 default: 90 assert(0); 91 break; 92 } 93} 94 95/* 96 * Static exported EXA functions 97 */ 98 99static void 100ExaWaitMarker(ScreenPtr pScreen, int marker) 101{ 102} 103 104static int 105ExaMarkSync(ScreenPtr pScreen) 106{ 107 return 1; 108} 109 110static Bool 111ExaPrepareAccess(PixmapPtr pPix, int index) 112{ 113 ScreenPtr pScreen = pPix->drawable.pScreen; 114 ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; 115 modesettingPtr ms = modesettingPTR(pScrn); 116 struct exa_entity *exa = ms->exa; 117 struct PixmapPriv *priv; 118 119 priv = exaGetPixmapDriverPrivate(pPix); 120 121 if (!priv) 122 return FALSE; 123 124 if (!priv->tex) 125 return FALSE; 126 127 if (priv->map_count++ == 0) 128 { 129 priv->map_transfer = 130 exa->scrn->get_tex_transfer(exa->scrn, priv->tex, 0, 0, 0, 131 PIPE_TRANSFER_READ_WRITE, 132 0, 0, priv->tex->width[0], priv->tex->height[0]); 133 134 pPix->devPrivate.ptr = 135 exa->scrn->transfer_map(exa->scrn, priv->map_transfer); 136 pPix->devKind = priv->map_transfer->stride; 137 } 138 139 return TRUE; 140} 141 142static void 143ExaFinishAccess(PixmapPtr pPix, int index) 144{ 145 ScreenPtr pScreen = pPix->drawable.pScreen; 146 ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; 147 modesettingPtr ms = modesettingPTR(pScrn); 148 struct exa_entity *exa = ms->exa; 149 struct PixmapPriv *priv; 150 priv = exaGetPixmapDriverPrivate(pPix); 151 152 if (!priv) 153 return; 154 155 if (!priv->map_transfer) 156 return; 157 158 if (--priv->map_count == 0) { 159 assert(priv->map_transfer); 160 exa->scrn->transfer_unmap(exa->scrn, priv->map_transfer); 161 exa->scrn->tex_transfer_destroy(priv->map_transfer); 162 priv->map_transfer = NULL; 163 } 164} 165 166static void 167ExaDone(PixmapPtr pPixmap) 168{ 169 ScrnInfoPtr pScrn = xf86Screens[pPixmap->drawable.pScreen->myNum]; 170 modesettingPtr ms = modesettingPTR(pScrn); 171 struct PixmapPriv *priv = exaGetPixmapDriverPrivate(pPixmap); 172 struct exa_entity *exa = ms->exa; 173 174 if (!priv) 175 return; 176 177 if (priv->src_surf) 178 exa->scrn->tex_surface_destroy(priv->src_surf); 179 priv->src_surf = NULL; 180} 181 182static void 183ExaDoneComposite(PixmapPtr pPixmap) 184{ 185 186} 187 188static Bool 189ExaPrepareSolid(PixmapPtr pPixmap, int alu, Pixel planeMask, Pixel fg) 190{ 191 ScrnInfoPtr pScrn = xf86Screens[pPixmap->drawable.pScreen->myNum]; 192 modesettingPtr ms = modesettingPTR(pScrn); 193 struct PixmapPriv *priv = exaGetPixmapDriverPrivate(pPixmap); 194 struct exa_entity *exa = ms->exa; 195 196 if (1) 197 return FALSE; 198 199 if (pPixmap->drawable.depth < 15) 200 return FALSE; 201 202 if (!EXA_PM_IS_SOLID(&pPixmap->drawable, planeMask)) 203 return FALSE; 204 205 if (!priv || !priv->tex) 206 return FALSE; 207 208 if (alu != GXcopy) 209 return FALSE; 210 211 if (!exa->ctx || !exa->ctx->surface_fill) 212 return FALSE; 213 214 priv->color = fg; 215 216 return TRUE; 217} 218 219static void 220ExaSolid(PixmapPtr pPixmap, int x0, int y0, int x1, int y1) 221{ 222 ScrnInfoPtr pScrn = xf86Screens[pPixmap->drawable.pScreen->myNum]; 223 modesettingPtr ms = modesettingPTR(pScrn); 224 struct exa_entity *exa = ms->exa; 225 struct PixmapPriv *priv = exaGetPixmapDriverPrivate(pPixmap); 226 struct pipe_surface *surf = 227 exa->scrn->get_tex_surface(exa->scrn, priv->tex, 0, 0, 0, 228 PIPE_BUFFER_USAGE_GPU_READ | 229 PIPE_BUFFER_USAGE_GPU_WRITE); 230 231 exa->ctx->surface_fill(exa->ctx, surf, x0, y0, x1 - x0, y1 - y0, 232 priv->color); 233 234 exa->scrn->tex_surface_destroy(surf); 235} 236 237static Bool 238ExaPrepareCopy(PixmapPtr pSrcPixmap, PixmapPtr pDstPixmap, int xdir, 239 int ydir, int alu, Pixel planeMask) 240{ 241 ScrnInfoPtr pScrn = xf86Screens[pDstPixmap->drawable.pScreen->myNum]; 242 modesettingPtr ms = modesettingPTR(pScrn); 243 struct exa_entity *exa = ms->exa; 244 struct PixmapPriv *priv = exaGetPixmapDriverPrivate(pDstPixmap); 245 struct PixmapPriv *src_priv = exaGetPixmapDriverPrivate(pSrcPixmap); 246 247 if (1) 248 return FALSE; 249 250 if (alu != GXcopy) 251 return FALSE; 252 253 if (pSrcPixmap->drawable.depth < 15 || pDstPixmap->drawable.depth < 15) 254 return FALSE; 255 256 if (!EXA_PM_IS_SOLID(&pSrcPixmap->drawable, planeMask)) 257 return FALSE; 258 259 if (!priv || !src_priv) 260 return FALSE; 261 262 if (!priv->tex || !src_priv->tex) 263 return FALSE; 264 265 if (!exa->ctx || !exa->ctx->surface_copy) 266 return FALSE; 267 268 priv->src_surf = 269 exa->scrn->get_tex_surface(exa->scrn, src_priv->tex, 0, 0, 0, 270 PIPE_BUFFER_USAGE_GPU_READ | 271 PIPE_BUFFER_USAGE_GPU_WRITE); 272 273 return TRUE; 274} 275 276static void 277ExaCopy(PixmapPtr pDstPixmap, int srcX, int srcY, int dstX, int dstY, 278 int width, int height) 279{ 280 ScrnInfoPtr pScrn = xf86Screens[pDstPixmap->drawable.pScreen->myNum]; 281 modesettingPtr ms = modesettingPTR(pScrn); 282 struct exa_entity *exa = ms->exa; 283 struct PixmapPriv *priv = exaGetPixmapDriverPrivate(pDstPixmap); 284 struct pipe_surface *surf = 285 exa->scrn->get_tex_surface(exa->scrn, priv->tex, 0, 0, 0, 286 PIPE_BUFFER_USAGE_GPU_READ | 287 PIPE_BUFFER_USAGE_GPU_WRITE); 288 289 exa->ctx->surface_copy(exa->ctx, surf, dstX, dstY, priv->src_surf, 290 srcX, srcY, width, height); 291 exa->scrn->tex_surface_destroy(surf); 292} 293 294static Bool 295ExaPrepareComposite(int op, PicturePtr pSrcPicture, 296 PicturePtr pMaskPicture, PicturePtr pDstPicture, 297 PixmapPtr pSrc, PixmapPtr pMask, PixmapPtr pDst) 298{ 299 return FALSE; 300} 301 302static void 303ExaComposite(PixmapPtr pDst, int srcX, int srcY, int maskX, int maskY, 304 int dstX, int dstY, int width, int height) 305{ 306} 307 308static Bool 309ExaCheckComposite(int op, 310 PicturePtr pSrcPicture, PicturePtr pMaskPicture, 311 PicturePtr pDstPicture) 312{ 313 return FALSE; 314} 315 316static void * 317ExaCreatePixmap(ScreenPtr pScreen, int size, int align) 318{ 319 struct PixmapPriv *priv; 320 321 priv = xcalloc(1, sizeof(struct PixmapPriv)); 322 if (!priv) 323 return NULL; 324 325 return priv; 326} 327 328static void 329ExaDestroyPixmap(ScreenPtr pScreen, void *dPriv) 330{ 331 struct PixmapPriv *priv = (struct PixmapPriv *)dPriv; 332 ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; 333 modesettingPtr ms = modesettingPTR(pScrn); 334 335 if (!priv) 336 return; 337 338 if (priv->tex) 339 ms->screen->texture_destroy(priv->tex); 340 341 xfree(priv); 342} 343 344static Bool 345ExaPixmapIsOffscreen(PixmapPtr pPixmap) 346{ 347 struct PixmapPriv *priv; 348 349 priv = exaGetPixmapDriverPrivate(pPixmap); 350 351 if (!priv) 352 return FALSE; 353 354 if (priv->tex) 355 return TRUE; 356 357 return FALSE; 358} 359 360unsigned 361xorg_exa_get_pixmap_handle(PixmapPtr pPixmap) 362{ 363 ScreenPtr pScreen = pPixmap->drawable.pScreen; 364 ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; 365 modesettingPtr ms = modesettingPTR(pScrn); 366 struct PixmapPriv *priv; 367 struct pipe_buffer *buffer = NULL; 368 unsigned handle; 369 unsigned stride; 370 371 if (!ms->exa) { 372 FatalError("NO MS->EXA\n"); 373 return 0; 374 } 375 376 priv = exaGetPixmapDriverPrivate(pPixmap); 377 378 if (!priv) { 379 FatalError("NO PIXMAP PRIVATE\n"); 380 return 0; 381 } 382 383 drm_api_hooks.buffer_from_texture(priv->tex, &buffer, &stride); 384 drm_api_hooks.handle_from_buffer(ms->screen, buffer, &handle); 385 pipe_buffer_reference(&buffer, NULL); 386 return handle; 387} 388 389static Bool 390ExaModifyPixmapHeader(PixmapPtr pPixmap, int width, int height, 391 int depth, int bitsPerPixel, int devKind, 392 pointer pPixData) 393{ 394 ScreenPtr pScreen = pPixmap->drawable.pScreen; 395 ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; 396 struct PixmapPriv *priv = exaGetPixmapDriverPrivate(pPixmap); 397 modesettingPtr ms = modesettingPTR(pScrn); 398 struct exa_entity *exa = ms->exa; 399 400 if (!priv) 401 return FALSE; 402 403 if (depth <= 0) 404 depth = pPixmap->drawable.depth; 405 406 if (bitsPerPixel <= 0) 407 bitsPerPixel = pPixmap->drawable.bitsPerPixel; 408 409 if (width <= 0) 410 width = pPixmap->drawable.width; 411 412 if (height <= 0) 413 height = pPixmap->drawable.height; 414 415 if (width <= 0 || height <= 0 || depth <= 0) 416 return FALSE; 417 418 miModifyPixmapHeader(pPixmap, width, height, depth, 419 bitsPerPixel, devKind, NULL); 420 421 /* Deal with screen resize */ 422 if (priv->tex && (priv->tex->width[0] != width || priv->tex->height[0] != height)) { 423 pipe_texture_reference(&priv->tex, NULL); 424 } 425 426 if (!priv->tex) { 427 struct pipe_texture template; 428 429 memset(&template, 0, sizeof(template)); 430 template.target = PIPE_TEXTURE_2D; 431 exa_get_pipe_format(depth, &template.format, &bitsPerPixel); 432 pf_get_block(template.format, &template.block); 433 template.width[0] = width; 434 template.height[0] = height; 435 template.depth[0] = 1; 436 template.last_level = 0; 437 template.tex_usage = PIPE_TEXTURE_USAGE_RENDER_TARGET; 438 priv->tex = exa->scrn->texture_create(exa->scrn, &template); 439 } 440 441 if (pPixData) { 442 struct pipe_transfer *transfer = 443 exa->scrn->get_tex_transfer(exa->scrn, priv->tex, 0, 0, 0, 444 PIPE_TRANSFER_WRITE, 445 0, 0, width, height); 446 pipe_copy_rect(exa->scrn->transfer_map(exa->scrn, transfer), 447 &priv->tex->block, transfer->stride, 0, 0, 448 width, height, pPixData, pPixmap->devKind, 0, 0); 449 exa->scrn->transfer_unmap(exa->scrn, transfer); 450 exa->scrn->tex_transfer_destroy(transfer); 451 } 452 453 return TRUE; 454} 455 456struct pipe_texture * 457xorg_exa_get_texture(PixmapPtr pPixmap) 458{ 459 struct PixmapPriv *priv = exaGetPixmapDriverPrivate(pPixmap); 460 struct pipe_texture *tex = NULL; 461 pipe_texture_reference(&tex, priv->tex); 462 return tex; 463} 464 465void 466xorg_exa_close(ScrnInfoPtr pScrn) 467{ 468 modesettingPtr ms = modesettingPTR(pScrn); 469 struct exa_entity *exa = ms->exa; 470 471 if (exa->ctx) 472 exa->ctx->destroy(exa->ctx); 473 474 exaDriverFini(pScrn->pScreen); 475 xfree(exa); 476 ms->exa = NULL; 477} 478 479void * 480xorg_exa_init(ScrnInfoPtr pScrn) 481{ 482 modesettingPtr ms = modesettingPTR(pScrn); 483 struct exa_entity *exa; 484 ExaDriverPtr pExa; 485 486 exa = xcalloc(1, sizeof(struct exa_entity)); 487 if (!exa) 488 return NULL; 489 490 pExa = exaDriverAlloc(); 491 if (!pExa) { 492 goto out_err; 493 } 494 495 memset(pExa, 0, sizeof(*pExa)); 496 pExa->exa_major = 2; 497 pExa->exa_minor = 2; 498 pExa->memoryBase = 0; 499 pExa->memorySize = 0; 500 pExa->offScreenBase = 0; 501 pExa->pixmapOffsetAlign = 0; 502 pExa->pixmapPitchAlign = 1; 503 pExa->flags = EXA_OFFSCREEN_PIXMAPS | EXA_HANDLES_PIXMAPS; 504 pExa->maxX = 8191; /* FIXME */ 505 pExa->maxY = 8191; /* FIXME */ 506 pExa->WaitMarker = ExaWaitMarker; 507 pExa->MarkSync = ExaMarkSync; 508 pExa->PrepareSolid = ExaPrepareSolid; 509 pExa->Solid = ExaSolid; 510 pExa->DoneSolid = ExaDone; 511 pExa->PrepareCopy = ExaPrepareCopy; 512 pExa->Copy = ExaCopy; 513 pExa->DoneCopy = ExaDone; 514 pExa->CheckComposite = ExaCheckComposite; 515 pExa->PrepareComposite = ExaPrepareComposite; 516 pExa->Composite = ExaComposite; 517 pExa->DoneComposite = ExaDoneComposite; 518 pExa->PixmapIsOffscreen = ExaPixmapIsOffscreen; 519 pExa->PrepareAccess = ExaPrepareAccess; 520 pExa->FinishAccess = ExaFinishAccess; 521 pExa->CreatePixmap = ExaCreatePixmap; 522 pExa->DestroyPixmap = ExaDestroyPixmap; 523 pExa->ModifyPixmapHeader = ExaModifyPixmapHeader; 524 525 if (!exaDriverInit(pScrn->pScreen, pExa)) { 526 goto out_err; 527 } 528 529 exa->scrn = ms->screen; 530 exa->ctx = drm_api_hooks.create_context(exa->scrn); 531 /* Share context with DRI */ 532 ms->ctx = exa->ctx; 533 534 return (void *)exa; 535 536 out_err: 537 xorg_exa_close(pScrn); 538 539 return NULL; 540} 541 542/* vim: set sw=4 ts=8 sts=4: */ 543