1/* 2 * Copyright 2010 Red Hat, Inc. 3 * 4 * Permission is hereby granted, free of charge, to any person obtaining a 5 * copy of this software and associated documentation files (the "Software"), 6 * to deal in the Software without restriction, including without limitation 7 * on the rights to use, copy, modify, merge, publish, distribute, sub 8 * license, and/or sell copies of the Software, and to permit persons to whom 9 * the Software is furnished to do so, subject to the following conditions: 10 * 11 * The above copyright notice and this permission notice (including the next 12 * paragraph) shall be included in all copies or substantial portions of the 13 * Software. 14 * 15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL 18 * THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 19 * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 20 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 21 */ 22 23#ifdef HAVE_CONFIG_H 24#include "config.h" 25#endif 26 27#include "qxl.h" 28#include "qxl_surface.h"/* send anything pending to the other side */ 29 30 31enum ROPDescriptor 32{ 33 ROPD_INVERS_SRC = (1 << 0), 34 ROPD_INVERS_BRUSH = (1 << 1), 35 ROPD_INVERS_DEST = (1 << 2), 36 ROPD_OP_PUT = (1 << 3), 37 ROPD_OP_OR = (1 << 4), 38 ROPD_OP_AND = (1 << 5), 39 ROPD_OP_XOR = (1 << 6), 40 ROPD_OP_BLACKNESS = (1 << 7), 41 ROPD_OP_WHITENESS = (1 << 8), 42 ROPD_OP_INVERS = (1 << 9), 43 ROPD_INVERS_RES = (1 <<10), 44}; 45 46static struct qxl_bo * 47make_drawable (qxl_screen_t *qxl, qxl_surface_t *surf, uint8_t type, 48 const struct QXLRect *rect 49 /* , pRegion clip */) 50{ 51 struct QXLDrawable *drawable; 52 struct qxl_bo *draw_bo; 53 int i; 54 55 draw_bo = qxl->bo_funcs->cmd_alloc (qxl, sizeof *drawable, "drawable command"); 56 assert(draw_bo); 57 drawable = qxl->bo_funcs->bo_map(draw_bo); 58 assert(drawable); 59 60 drawable->release_info.id = pointer_to_u64 (draw_bo); 61 62 drawable->type = type; 63 64 qxl->bo_funcs->bo_output_surf_reloc(qxl, offsetof(struct QXLDrawable, surface_id), draw_bo, surf); 65 66 drawable->effect = QXL_EFFECT_OPAQUE; 67 drawable->self_bitmap = 0; 68 drawable->self_bitmap_area.top = 0; 69 drawable->self_bitmap_area.left = 0; 70 drawable->self_bitmap_area.bottom = 0; 71 drawable->self_bitmap_area.right = 0; 72 /* FIXME: add clipping */ 73 drawable->clip.type = SPICE_CLIP_TYPE_NONE; 74 75 /* 76 * surfaces_dest[i] should apparently be filled out with the 77 * surfaces that we depend on, and surface_rects should be 78 * filled with the rectangles of those surfaces that we 79 * are going to use. 80 */ 81 for (i = 0; i < 3; ++i) 82 drawable->surfaces_dest[i] = -1; 83 84 if (rect) 85 drawable->bbox = *rect; 86 87 /* No longer needed since spice-server commit c541d7e29 */ 88 if (!qxl->kms_enabled) 89 drawable->mm_time = qxl->rom->mm_clock; 90 else 91 drawable->mm_time = 0; 92 93 qxl->bo_funcs->bo_unmap(draw_bo); 94 return draw_bo; 95} 96 97static void 98push_drawable (qxl_screen_t *qxl, struct qxl_bo *drawable_bo) 99{ 100 qxl->bo_funcs->write_command (qxl, QXL_CMD_DRAW, drawable_bo); 101} 102 103static void 104submit_fill (qxl_screen_t *qxl, qxl_surface_t *surf, 105 const struct QXLRect *rect, uint32_t color) 106{ 107 struct qxl_bo *drawable_bo; 108 struct QXLDrawable *drawable; 109 110 drawable_bo = make_drawable (qxl, surf, QXL_DRAW_FILL, rect); 111 112 drawable = qxl->bo_funcs->bo_map(drawable_bo); 113 drawable->u.fill.brush.type = SPICE_BRUSH_TYPE_SOLID; 114 drawable->u.fill.brush.u.color = color; 115 drawable->u.fill.rop_descriptor = ROPD_OP_PUT; 116 drawable->u.fill.mask.flags = 0; 117 drawable->u.fill.mask.pos.x = 0; 118 drawable->u.fill.mask.pos.y = 0; 119 drawable->u.fill.mask.bitmap = 0; 120 121 qxl->bo_funcs->bo_unmap(drawable_bo); 122 123 push_drawable (qxl, drawable_bo); 124} 125 126void 127qxl_surface_flush (qxl_surface_t *surface) 128{ 129 ; 130} 131 132/* access */ 133static void 134download_box_no_update (qxl_surface_t *surface, int x1, int y1, int x2, int y2) 135{ 136 pixman_image_composite (PIXMAN_OP_SRC, 137 surface->dev_image, 138 NULL, 139 surface->host_image, 140 x1, y1, 0, 0, x1, y1, x2 - x1, y2 - y1); 141} 142 143void 144qxl_download_box (qxl_surface_t *surface, int x1, int y1, int x2, int y2) 145{ 146 assert (x2 >= x1 && y2 >= y1); 147 148 if (x1 == x2 || y1 == y2) 149 return; 150 151 surface->qxl->bo_funcs->update_area(surface, x1, y1, x2, y2); 152 153 download_box_no_update(surface, x1, y1, x2, y2); 154} 155 156Bool 157qxl_surface_prepare_access (qxl_surface_t *surface, 158 PixmapPtr pixmap, 159 RegionPtr region, 160 uxa_access_t access) 161{ 162 int n_boxes; 163 BoxPtr boxes; 164 ScreenPtr pScreen = pixmap->drawable.pScreen; 165 ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen); 166 RegionRec new; 167 168 if (!pScrn->vtSema) 169 return FALSE; 170 171 REGION_INIT (NULL, &new, (BoxPtr)NULL, 0); 172 REGION_SUBTRACT (NULL, &new, region, &surface->access_region); 173 174 if (access == UXA_ACCESS_RW) 175 surface->access_type = UXA_ACCESS_RW; 176 177 region = &new; 178 179 n_boxes = REGION_NUM_RECTS (region); 180 boxes = REGION_RECTS (region); 181 182 if (n_boxes < 25) 183 { 184 while (n_boxes--) 185 { 186 qxl_download_box (surface, boxes->x1, boxes->y1, boxes->x2, boxes->y2); 187 188 boxes++; 189 } 190 } 191 else 192 { 193 qxl_download_box ( 194 surface, 195 new.extents.x1, new.extents.y1, new.extents.x2, new.extents.y2); 196 } 197 198 REGION_UNION (pScreen, 199 &(surface->access_region), 200 &(surface->access_region), 201 region); 202 203 REGION_UNINIT (NULL, &new); 204 205 pScreen->ModifyPixmapHeader( 206 pixmap, 207 pixmap->drawable.width, 208 pixmap->drawable.height, 209 -1, -1, -1, 210 pixman_image_get_data (surface->host_image)); 211 212 pixmap->devKind = pixman_image_get_stride (surface->host_image); 213 214 return TRUE; 215} 216 217static void 218translate_rect (struct QXLRect *rect) 219{ 220 rect->right -= rect->left; 221 rect->bottom -= rect->top; 222 rect->left = rect->top = 0; 223} 224 225static void 226real_upload_box (qxl_surface_t *surface, int x1, int y1, int x2, int y2) 227{ 228 struct QXLRect rect; 229 struct QXLDrawable *drawable; 230 struct qxl_bo *image_bo, *drawable_bo; 231 qxl_screen_t *qxl = surface->qxl; 232 uint32_t *data; 233 int stride; 234 235 rect.left = x1; 236 rect.right = x2; 237 rect.top = y1; 238 rect.bottom = y2; 239 240 drawable_bo = make_drawable (qxl, surface, QXL_DRAW_COPY, &rect); 241 drawable = qxl->bo_funcs->bo_map(drawable_bo); 242 drawable->u.copy.src_area = rect; 243 translate_rect (&drawable->u.copy.src_area); 244 drawable->u.copy.rop_descriptor = ROPD_OP_PUT; 245 drawable->u.copy.scale_mode = 0; 246 drawable->u.copy.mask.flags = 0; 247 drawable->u.copy.mask.pos.x = 0; 248 drawable->u.copy.mask.pos.y = 0; 249 drawable->u.copy.mask.bitmap = 0; 250 251 qxl->bo_funcs->bo_unmap(drawable_bo); 252 253 data = pixman_image_get_data (surface->host_image); 254 stride = pixman_image_get_stride (surface->host_image); 255 256 image_bo = qxl_image_create ( 257 qxl, (const uint8_t *)data, x1, y1, x2 - x1, y2 - y1, stride, 258 surface->bpp == 24 ? 4 : surface->bpp / 8, TRUE); 259 qxl->bo_funcs->bo_output_bo_reloc(qxl, offsetof(QXLDrawable, u.copy.src_bitmap), 260 drawable_bo, image_bo); 261 push_drawable (qxl, drawable_bo); 262 263 qxl->bo_funcs->bo_decref(qxl, image_bo); 264} 265 266#define TILE_WIDTH 512 267#define TILE_HEIGHT 512 268 269void 270qxl_upload_box (qxl_surface_t *surface, int x1, int y1, int x2, int y2) 271{ 272 int tile_x1, tile_y1; 273 274 for (tile_y1 = y1; tile_y1 < y2; tile_y1 += TILE_HEIGHT) 275 { 276 for (tile_x1 = x1; tile_x1 < x2; tile_x1 += TILE_WIDTH) 277 { 278 int tile_x2 = tile_x1 + TILE_WIDTH; 279 int tile_y2 = tile_y1 + TILE_HEIGHT; 280 281 if (tile_x2 > x2) 282 tile_x2 = x2; 283 if (tile_y2 > y2) 284 tile_y2 = y2; 285 286 real_upload_box (surface, tile_x1, tile_y1, tile_x2, tile_y2); 287 } 288 } 289} 290 291static void 292upload_one_primary_region(qxl_screen_t *qxl, PixmapPtr pixmap, BoxPtr b) 293{ 294 struct QXLRect rect; 295 struct qxl_bo *drawable_bo, *image_bo; 296 struct QXLDrawable *drawable; 297 FbBits *data; 298 int stride; 299 int bpp; 300 301 if (b->x1 >= qxl->virtual_x || b->y1 >= qxl->virtual_y) 302 return; 303 304 rect.left = b->x1; 305 rect.right = min(b->x2, qxl->virtual_x); 306 rect.top = b->y1; 307 rect.bottom = min(b->y2, qxl->virtual_y); 308 309 drawable_bo = make_drawable (qxl, qxl->primary, QXL_DRAW_COPY, &rect); 310 drawable = qxl->bo_funcs->bo_map(drawable_bo); 311 drawable->u.copy.src_area = rect; 312 translate_rect (&drawable->u.copy.src_area); 313 drawable->u.copy.rop_descriptor = ROPD_OP_PUT; 314 drawable->u.copy.scale_mode = 0; 315 drawable->u.copy.mask.flags = 0; 316 drawable->u.copy.mask.pos.x = 0; 317 drawable->u.copy.mask.pos.y = 0; 318 drawable->u.copy.mask.bitmap = 0; 319 qxl->bo_funcs->bo_unmap(drawable_bo); 320 321 fbGetPixmapBitsData(pixmap, data, stride, bpp); 322 image_bo = qxl_image_create ( 323 qxl, (const uint8_t *)data, rect.left, rect.top, rect.right - rect.left, rect.bottom - rect.top, stride * sizeof(*data), 324 bpp == 24 ? 4 : bpp / 8, TRUE); 325 qxl->bo_funcs->bo_output_bo_reloc(qxl, offsetof(QXLDrawable, u.copy.src_bitmap), 326 drawable_bo, image_bo); 327 328 push_drawable (qxl, drawable_bo); 329 qxl->bo_funcs->bo_decref(qxl, image_bo); 330} 331 332void 333qxl_surface_upload_primary_regions(qxl_screen_t *qxl, PixmapPtr pixmap, RegionRec *r) 334{ 335 int n_boxes; 336 BoxPtr boxes; 337 338 n_boxes = RegionNumRects(r); 339 boxes = RegionRects(r); 340 341 while (n_boxes--) 342 { 343 upload_one_primary_region(qxl, pixmap, boxes); 344 boxes++; 345 } 346} 347 348void 349qxl_surface_finish_access (qxl_surface_t *surface, PixmapPtr pixmap) 350{ 351 ScreenPtr pScreen = pixmap->drawable.pScreen; 352 int w = pixmap->drawable.width; 353 int h = pixmap->drawable.height; 354 int n_boxes; 355 BoxPtr boxes; 356 357 n_boxes = REGION_NUM_RECTS (&surface->access_region); 358 boxes = REGION_RECTS (&surface->access_region); 359 360 if (surface->access_type == UXA_ACCESS_RW) 361 { 362 if (n_boxes < 25) 363 { 364 while (n_boxes--) 365 { 366 qxl_upload_box (surface, boxes->x1, boxes->y1, boxes->x2, boxes->y2); 367 368 boxes++; 369 } 370 } 371 else 372 { 373 qxl_upload_box (surface, 374 surface->access_region.extents.x1, 375 surface->access_region.extents.y1, 376 surface->access_region.extents.x2, 377 surface->access_region.extents.y2); 378 } 379 } 380 381 REGION_EMPTY (pScreen, &surface->access_region); 382 surface->access_type = UXA_ACCESS_RO; 383 384 pScreen->ModifyPixmapHeader(pixmap, w, h, -1, -1, 0, NULL); 385} 386 387 388#ifdef DEBUG_REGIONS 389static void 390print_region (const char *header, RegionPtr pRegion) 391{ 392 int nbox = REGION_NUM_RECTS (pRegion); 393 BoxPtr pbox = REGION_RECTS (pRegion); 394 395 ErrorF ("%s", header); 396 397 if (nbox == 0) 398 ErrorF (" (empty)\n"); 399 else 400 ErrorF ("\n"); 401 402 while (nbox--) 403 { 404 ErrorF (" %d %d %d %d (size: %d %d)\n", 405 pbox->x1, pbox->y1, pbox->x2, pbox->y2, 406 pbox->x2 - pbox->x1, pbox->y2 - pbox->y1); 407 408 pbox++; 409 } 410} 411#endif // DEBUG_REGIONS 412 413/* solid */ 414Bool 415qxl_surface_prepare_solid (qxl_surface_t *destination, 416 Pixel fg) 417{ 418 if (!REGION_NIL (&(destination->access_region))) 419 { 420 ErrorF (" solid not in vmem\n"); 421 } 422 423#ifdef DEBUG_REGIONS 424 print_region ("prepare solid", &(destination->access_region)); 425#endif 426 427 destination->u.solid_pixel = fg; // ^ (rand() >> 16); 428 429 return TRUE; 430} 431 432void 433qxl_surface_solid (qxl_surface_t *destination, 434 int x1, 435 int y1, 436 int x2, 437 int y2) 438{ 439 qxl_screen_t *qxl = destination->qxl; 440 struct QXLRect qrect; 441 uint32_t p; 442 443 qrect.top = y1; 444 qrect.bottom = y2; 445 qrect.left = x1; 446 qrect.right = x2; 447 448 p = destination->u.solid_pixel; 449 450 submit_fill (qxl, destination, &qrect, p); 451} 452 453/* copy */ 454Bool 455qxl_surface_prepare_copy (qxl_surface_t *dest, 456 qxl_surface_t *source) 457{ 458 if (!REGION_NIL (&(dest->access_region)) || 459 !REGION_NIL (&(source->access_region))) 460 { 461 return FALSE; 462 } 463 464 dest->u.copy_src = source; 465 466 return TRUE; 467} 468 469 470static struct qxl_bo * 471image_from_surface_internal(qxl_screen_t *qxl, 472 qxl_surface_t *surface) 473{ 474 struct qxl_bo *image_bo = qxl->bo_funcs->bo_alloc (qxl, sizeof(struct QXLImage), "image struct for surface"); 475 struct QXLImage *image = qxl->bo_funcs->bo_map(image_bo); 476 477 image->descriptor.id = 0; 478 image->descriptor.type = SPICE_IMAGE_TYPE_SURFACE; 479 image->descriptor.width = 0; 480 image->descriptor.height = 0; 481 qxl->bo_funcs->bo_unmap(image_bo); 482 return image_bo; 483} 484 485static struct qxl_bo *image_from_surface(qxl_screen_t *qxl, qxl_surface_t *dest) 486{ 487 if (!dest->image_bo) 488 dest->image_bo = image_from_surface_internal(qxl, dest); 489 490 qxl->bo_funcs->bo_incref(qxl, dest->image_bo); 491 qxl->bo_funcs->bo_output_surf_reloc(qxl, offsetof(struct QXLImage, surface_image.surface_id), dest->image_bo, dest); 492 493 return dest->image_bo; 494} 495 496void 497qxl_surface_copy (qxl_surface_t *dest, 498 int src_x1, int src_y1, 499 int dest_x1, int dest_y1, 500 int width, int height) 501{ 502 qxl_screen_t *qxl = dest->qxl; 503 struct qxl_bo *drawable_bo; 504 struct QXLDrawable *drawable; 505 struct QXLRect qrect; 506 507#ifdef DEBUG_REGIONS 508 print_region (" copy src", &(dest->u.copy_src->access_region)); 509 print_region (" copy dest", &(dest->access_region)); 510#endif 511 512 qrect.top = dest_y1; 513 qrect.bottom = dest_y1 + height; 514 qrect.left = dest_x1; 515 qrect.right = dest_x1 + width; 516 517 if (dest->id == dest->u.copy_src->id) 518 { 519 drawable_bo = make_drawable (qxl, dest, QXL_COPY_BITS, &qrect); 520 521 drawable = qxl->bo_funcs->bo_map(drawable_bo); 522 drawable->u.copy_bits.src_pos.x = src_x1; 523 drawable->u.copy_bits.src_pos.y = src_y1; 524 qxl->bo_funcs->bo_unmap(drawable_bo); 525 526 push_drawable (qxl, drawable_bo); 527 528 } 529 else 530 { 531 struct qxl_bo *image_bo; 532 533 dest->u.copy_src->ref_count++; 534 535 image_bo = image_from_surface(qxl, dest->u.copy_src); 536 537 drawable_bo = make_drawable (qxl, dest, QXL_DRAW_COPY, &qrect); 538 539 drawable = qxl->bo_funcs->bo_map(drawable_bo); 540 qxl->bo_funcs->bo_output_bo_reloc(qxl, offsetof(QXLDrawable, u.copy.src_bitmap), 541 drawable_bo, image_bo); 542 drawable->u.copy.src_area.left = src_x1; 543 drawable->u.copy.src_area.top = src_y1; 544 drawable->u.copy.src_area.right = src_x1 + width; 545 drawable->u.copy.src_area.bottom = src_y1 + height; 546 drawable->u.copy.rop_descriptor = ROPD_OP_PUT; 547 drawable->u.copy.scale_mode = 0; 548 drawable->u.copy.mask.flags = 0; 549 drawable->u.copy.mask.pos.x = 0; 550 drawable->u.copy.mask.pos.y = 0; 551 drawable->u.copy.mask.bitmap = 0; 552 553 qxl->bo_funcs->bo_output_surf_reloc(qxl, offsetof(struct QXLDrawable, surfaces_dest[0]), drawable_bo, dest->u.copy_src); 554 drawable->surfaces_rects[0] = drawable->u.copy.src_area; 555 556 assert (src_x1 >= 0); 557 assert (src_y1 >= 0); 558 559 if (width > pixman_image_get_width (dest->u.copy_src->host_image)) 560 { 561 ErrorF ("dest w: %d src w: %d\n", 562 width, pixman_image_get_width (dest->u.copy_src->host_image)); 563 } 564 565 assert (width <= pixman_image_get_width (dest->u.copy_src->host_image)); 566 assert (height <= pixman_image_get_height (dest->u.copy_src->host_image)); 567 568 qxl->bo_funcs->bo_unmap(drawable_bo); 569 push_drawable (qxl, drawable_bo); 570 qxl->bo_funcs->bo_decref(qxl, image_bo); 571 } 572} 573 574/* composite */ 575Bool 576qxl_surface_prepare_composite (int op, 577 PicturePtr src_picture, 578 PicturePtr mask_picture, 579 PicturePtr dest_picture, 580 qxl_surface_t * src, 581 qxl_surface_t * mask, 582 qxl_surface_t * dest) 583{ 584 dest->u.composite.op = op; 585 dest->u.composite.src_picture = src_picture; 586 dest->u.composite.mask_picture = mask_picture; 587 dest->u.composite.dest_picture = dest_picture; 588 dest->u.composite.src = src; 589 dest->u.composite.mask = mask; 590 dest->u.composite.dest = dest; 591 592 return TRUE; 593} 594 595static struct qxl_bo * 596image_from_picture (qxl_screen_t *qxl, 597 PicturePtr picture, 598 qxl_surface_t *surface, 599 int *force_opaque) 600{ 601 if (picture->format == PICT_x8r8g8b8) 602 *force_opaque = TRUE; 603 else 604 *force_opaque = FALSE; 605 606 return image_from_surface(qxl, surface); 607} 608 609static struct qxl_bo * 610get_transform (qxl_screen_t *qxl, PictTransform *transform) 611{ 612 if (transform) 613 { 614 struct qxl_bo *qxform_bo = qxl->bo_funcs->bo_alloc (qxl, sizeof (QXLTransform), "transform"); 615 QXLTransform *qxform = qxl->bo_funcs->bo_map(qxform_bo); 616 617 qxform->t00 = transform->matrix[0][0]; 618 qxform->t01 = transform->matrix[0][1]; 619 qxform->t02 = transform->matrix[0][2]; 620 qxform->t10 = transform->matrix[1][0]; 621 qxform->t11 = transform->matrix[1][1]; 622 qxform->t12 = transform->matrix[1][2]; 623 624 qxl->bo_funcs->bo_unmap(qxform_bo); 625 return qxform_bo; 626 } 627 else 628 { 629 return NULL; 630 } 631} 632 633static QXLRect 634full_rect (qxl_surface_t *surface) 635{ 636 QXLRect r; 637 int w = pixman_image_get_width (surface->host_image); 638 int h = pixman_image_get_height (surface->host_image); 639 640 r.left = r.top = 0; 641 r.right = w; 642 r.bottom = h; 643 644 return r; 645} 646 647void 648qxl_surface_composite (qxl_surface_t *dest, 649 int src_x, int src_y, 650 int mask_x, int mask_y, 651 int dest_x, int dest_y, 652 int width, int height) 653{ 654 qxl_screen_t *qxl = dest->qxl; 655 PicturePtr src = dest->u.composite.src_picture; 656 qxl_surface_t *qsrc = dest->u.composite.src; 657 PicturePtr mask = dest->u.composite.mask_picture; 658 qxl_surface_t *qmask = dest->u.composite.mask; 659 int op = dest->u.composite.op; 660 struct QXLDrawable *drawable; 661 struct qxl_bo *drawable_bo; 662 QXLComposite *composite; 663 QXLRect rect; 664 struct qxl_bo *trans_bo, *img_bo; 665 int n_deps = 0; 666 int force_opaque; 667 struct qxl_bo *derefs[4]; 668 int n_derefs = 0, i; 669#if 0 670 ErrorF ("QXL Composite: src: %x (%d %d) id: %d; \n" 671 " mask: id: %d\n" 672 " dest: %x %d %d %d %d (id: %d)\n", 673 dest->u.composite.src_picture->format, 674 dest->u.composite.src_picture->pDrawable->width, 675 dest->u.composite.src_picture->pDrawable->height, 676 dest->u.composite.src->id, 677 dest->u.composite.mask? dest->u.composite.mask->id : -1, 678 dest->u.composite.dest_picture->format, 679 dest_x, dest_y, width, height, 680 dest->id 681 ); 682#endif 683 684 rect.left = dest_x; 685 rect.right = dest_x + width; 686 rect.top = dest_y; 687 rect.bottom = dest_y + height; 688 689 drawable_bo = make_drawable (qxl, dest, QXL_DRAW_COMPOSITE, &rect); 690 691 drawable = qxl->bo_funcs->bo_map(drawable_bo); 692 693 composite = &drawable->u.composite; 694 695 composite->flags = 0; 696 697 if (dest->u.composite.dest_picture->format == PICT_x8r8g8b8) 698 composite->flags |= SPICE_COMPOSITE_DEST_OPAQUE; 699 700 composite->flags |= (op & 0xff); 701 702 img_bo = image_from_picture (qxl, src, qsrc, &force_opaque); 703 if (force_opaque) 704 composite->flags |= SPICE_COMPOSITE_SOURCE_OPAQUE; 705 qxl->bo_funcs->bo_output_bo_reloc(qxl, offsetof(QXLDrawable, u.composite.src), 706 drawable_bo, img_bo); 707 derefs[n_derefs++] = img_bo; 708 709 composite->flags |= (src->filter << 8); 710 composite->flags |= (src->repeat << 14); 711 trans_bo = get_transform (qxl, src->transform); 712 if (trans_bo) { 713 qxl->bo_funcs->bo_output_bo_reloc(qxl, offsetof(QXLDrawable, u.composite.src_transform), 714 drawable_bo, trans_bo); 715 derefs[n_derefs++] = trans_bo; 716 } else 717 composite->src_transform = 0; 718 719 qxl->bo_funcs->bo_output_surf_reloc(qxl, offsetof(struct QXLDrawable, surfaces_dest[n_deps]), drawable_bo, qsrc); 720 drawable->surfaces_rects[n_deps] = full_rect (qsrc); 721 722 n_deps++; 723 724 if (mask) 725 { 726 img_bo = image_from_picture (qxl, mask, qmask, &force_opaque); 727 if (force_opaque) 728 composite->flags |= SPICE_COMPOSITE_MASK_OPAQUE; 729 730 qxl->bo_funcs->bo_output_bo_reloc(qxl, offsetof(QXLDrawable, u.composite.mask), 731 drawable_bo, img_bo); 732 derefs[n_derefs++] = img_bo; 733 composite->flags |= (mask->filter << 11); 734 composite->flags |= (mask->repeat << 16); 735 composite->flags |= (mask->componentAlpha << 18); 736 737 qxl->bo_funcs->bo_output_surf_reloc(qxl, offsetof(struct QXLDrawable, surfaces_dest[n_deps]), drawable_bo, qmask); 738 drawable->surfaces_rects[n_deps] = full_rect (qmask); 739 n_deps++; 740 741 trans_bo = get_transform (qxl, src->transform); 742 if (trans_bo) { 743 qxl->bo_funcs->bo_output_bo_reloc(qxl, offsetof(QXLDrawable, u.composite.mask_transform), 744 drawable_bo, trans_bo); 745 derefs[n_derefs++] = trans_bo; 746 } 747 else 748 composite->mask_transform = 0; 749 } 750 else 751 { 752 composite->mask = 0x00000000; 753 composite->mask_transform = 0x00000000; 754 } 755 756 qxl->bo_funcs->bo_output_surf_reloc(qxl, offsetof(struct QXLDrawable, surfaces_dest[n_deps]), drawable_bo, dest); 757 drawable->surfaces_rects[n_deps] = full_rect (dest); 758 759 composite->src_origin.x = src_x; 760 composite->src_origin.y = src_y; 761 composite->mask_origin.x = mask_x; 762 composite->mask_origin.y = mask_y; 763 764 drawable->effect = QXL_EFFECT_BLEND; 765 766 qxl->bo_funcs->bo_unmap(drawable_bo); 767 push_drawable (qxl, drawable_bo); 768 769 for (i = 0; i < n_derefs; i++) 770 qxl->bo_funcs->bo_decref(qxl, derefs[i]); 771} 772 773Bool 774qxl_surface_put_image (qxl_surface_t *dest, 775 int x, int y, int width, int height, 776 const char *src, int src_pitch) 777{ 778 struct qxl_bo *drawable_bo; 779 struct QXLDrawable *drawable; 780 qxl_screen_t *qxl = dest->qxl; 781 struct QXLRect rect; 782 struct qxl_bo *image_bo; 783 784 rect.left = x; 785 rect.right = x + width; 786 rect.top = y; 787 rect.bottom = y + height; 788 789 drawable_bo = make_drawable (qxl, dest, QXL_DRAW_COPY, &rect); 790 791 drawable = qxl->bo_funcs->bo_map(drawable_bo); 792 drawable->u.copy.src_area.top = 0; 793 drawable->u.copy.src_area.bottom = height; 794 drawable->u.copy.src_area.left = 0; 795 drawable->u.copy.src_area.right = width; 796 797 drawable->u.copy.rop_descriptor = ROPD_OP_PUT; 798 drawable->u.copy.scale_mode = 0; 799 drawable->u.copy.mask.flags = 0; 800 drawable->u.copy.mask.pos.x = 0; 801 drawable->u.copy.mask.pos.y = 0; 802 drawable->u.copy.mask.bitmap = 0; 803 804 image_bo = qxl_image_create ( 805 qxl, (const uint8_t *)src, 0, 0, width, height, src_pitch, 806 dest->bpp == 24 ? 4 : dest->bpp / 8, FALSE); 807 qxl->bo_funcs->bo_output_bo_reloc(qxl, offsetof(QXLDrawable, u.copy.src_bitmap), 808 drawable_bo, image_bo); 809 810 qxl->bo_funcs->bo_unmap(drawable_bo); 811 812 push_drawable (qxl, drawable_bo); 813 qxl->bo_funcs->bo_decref(qxl, image_bo); 814 return TRUE; 815} 816 817void 818qxl_get_formats (int bpp, SpiceSurfaceFmt *format, pixman_format_code_t *pformat) 819{ 820 switch (bpp) 821 { 822 case 8: 823 *format = SPICE_SURFACE_FMT_8_A; 824 *pformat = PIXMAN_a8; 825 break; 826 827 case 16: 828 *format = SPICE_SURFACE_FMT_16_565; 829 *pformat = PIXMAN_r5g6b5; 830 break; 831 832 case 24: 833 *format = SPICE_SURFACE_FMT_32_xRGB; 834 *pformat = PIXMAN_a8r8g8b8; 835 break; 836 837 case 32: 838 *format = SPICE_SURFACE_FMT_32_ARGB; 839 *pformat = PIXMAN_a8r8g8b8; 840 break; 841 842 default: 843 *format = -1; 844 *pformat = -1; 845 break; 846 } 847} 848