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