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