os: if inet_ntop() is available, use it for IPv4 addresses as well
[xserver.git] / glamor / glamor_copy.c
blob9095653681389a7e007882155d2cf5dcddfaad0c
1 /*
2 * Copyright © 2014 Keith Packard
4 * Permission to use, copy, modify, distribute, and sell this software and its
5 * documentation for any purpose is hereby granted without fee, provided that
6 * the above copyright notice appear in all copies and that both that copyright
7 * notice and this permission notice appear in supporting documentation, and
8 * that the name of the copyright holders not be used in advertising or
9 * publicity pertaining to distribution of the software without specific,
10 * written prior permission. The copyright holders make no representations
11 * about the suitability of this software for any purpose. It is provided "as
12 * is" without express or implied warranty.
14 * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
15 * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
16 * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
17 * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
18 * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
19 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
20 * OF THIS SOFTWARE.
23 #include "glamor_priv.h"
24 #include "glamor_transfer.h"
25 #include "glamor_prepare.h"
26 #include "glamor_transform.h"
28 struct copy_args {
29 DrawablePtr src_drawable;
30 glamor_pixmap_fbo *src;
31 uint32_t bitplane;
32 int dx, dy;
35 static Bool
36 use_copyarea(DrawablePtr drawable, GCPtr gc, glamor_program *prog, void *arg)
38 struct copy_args *args = arg;
39 glamor_pixmap_fbo *src = args->src;
41 glamor_bind_texture(glamor_get_screen_private(drawable->pScreen),
42 GL_TEXTURE0, src, TRUE);
44 glUniform2f(prog->fill_offset_uniform, args->dx, args->dy);
45 glUniform2f(prog->fill_size_inv_uniform, 1.0f/src->width, 1.0f/src->height);
47 return TRUE;
50 static const glamor_facet glamor_facet_copyarea = {
51 "copy_area",
52 .vs_vars = "in vec2 primitive;\n",
53 .vs_exec = (GLAMOR_POS(gl_Position, primitive.xy)
54 " fill_pos = (fill_offset + primitive.xy) * fill_size_inv;\n"),
55 .fs_exec = " frag_color = texture(sampler, fill_pos);\n",
56 .locations = glamor_program_location_fillsamp | glamor_program_location_fillpos,
57 .use = use_copyarea,
61 * Configure the copy plane program for the current operation
64 static Bool
65 use_copyplane(DrawablePtr drawable, GCPtr gc, glamor_program *prog, void *arg)
67 struct copy_args *args = arg;
68 glamor_pixmap_fbo *src = args->src;
70 glamor_bind_texture(glamor_get_screen_private(drawable->pScreen),
71 GL_TEXTURE0, src, TRUE);
73 glUniform2f(prog->fill_offset_uniform, args->dx, args->dy);
74 glUniform2f(prog->fill_size_inv_uniform, 1.0f/src->width, 1.0f/src->height);
76 glamor_set_color(drawable, gc->fgPixel, prog->fg_uniform);
77 glamor_set_color(drawable, gc->bgPixel, prog->bg_uniform);
79 /* XXX handle 2 10 10 10 and 1555 formats; presumably the pixmap private knows this? */
80 switch (glamor_drawable_effective_depth(args->src_drawable)) {
81 case 30:
82 glUniform4ui(prog->bitplane_uniform,
83 (args->bitplane >> 20) & 0x3ff,
84 (args->bitplane >> 10) & 0x3ff,
85 (args->bitplane ) & 0x3ff,
86 0);
88 glUniform4f(prog->bitmul_uniform, 0x3ff, 0x3ff, 0x3ff, 0);
89 break;
90 case 24:
91 glUniform4ui(prog->bitplane_uniform,
92 (args->bitplane >> 16) & 0xff,
93 (args->bitplane >> 8) & 0xff,
94 (args->bitplane ) & 0xff,
95 0);
97 glUniform4f(prog->bitmul_uniform, 0xff, 0xff, 0xff, 0);
98 break;
99 case 32:
100 glUniform4ui(prog->bitplane_uniform,
101 (args->bitplane >> 16) & 0xff,
102 (args->bitplane >> 8) & 0xff,
103 (args->bitplane ) & 0xff,
104 (args->bitplane >> 24) & 0xff);
106 glUniform4f(prog->bitmul_uniform, 0xff, 0xff, 0xff, 0xff);
107 break;
108 case 16:
109 glUniform4ui(prog->bitplane_uniform,
110 (args->bitplane >> 11) & 0x1f,
111 (args->bitplane >> 5) & 0x3f,
112 (args->bitplane ) & 0x1f,
115 glUniform4f(prog->bitmul_uniform, 0x1f, 0x3f, 0x1f, 0);
116 break;
117 case 15:
118 glUniform4ui(prog->bitplane_uniform,
119 (args->bitplane >> 10) & 0x1f,
120 (args->bitplane >> 5) & 0x1f,
121 (args->bitplane ) & 0x1f,
124 glUniform4f(prog->bitmul_uniform, 0x1f, 0x1f, 0x1f, 0);
125 break;
126 case 8:
127 glUniform4ui(prog->bitplane_uniform,
128 0, 0, 0, args->bitplane);
129 glUniform4f(prog->bitmul_uniform, 0, 0, 0, 0xff);
130 break;
131 case 1:
132 glUniform4ui(prog->bitplane_uniform,
133 0, 0, 0, args->bitplane);
134 glUniform4f(prog->bitmul_uniform, 0, 0, 0, 0xff);
135 break;
138 return TRUE;
141 static const glamor_facet glamor_facet_copyplane = {
142 "copy_plane",
143 .version = 130,
144 .vs_vars = "in vec2 primitive;\n",
145 .vs_exec = (GLAMOR_POS(gl_Position, (primitive.xy))
146 " fill_pos = (fill_offset + primitive.xy) * fill_size_inv;\n"),
147 .fs_exec = (" uvec4 bits = uvec4(round(texture(sampler, fill_pos) * bitmul));\n"
148 " if ((bits & bitplane) != uvec4(0,0,0,0))\n"
149 " frag_color = fg;\n"
150 " else\n"
151 " frag_color = bg;\n"),
152 .locations = glamor_program_location_fillsamp|glamor_program_location_fillpos|glamor_program_location_fg|glamor_program_location_bg|glamor_program_location_bitplane,
153 .use = use_copyplane,
157 * When all else fails, pull the bits out of the GPU and do the
158 * operation with fb
161 static void
162 glamor_copy_bail(DrawablePtr src,
163 DrawablePtr dst,
164 GCPtr gc,
165 BoxPtr box,
166 int nbox,
167 int dx,
168 int dy,
169 Bool reverse,
170 Bool upsidedown,
171 Pixel bitplane,
172 void *closure)
174 if (glamor_prepare_access(dst, GLAMOR_ACCESS_RW) && glamor_prepare_access(src, GLAMOR_ACCESS_RO)) {
175 if (bitplane) {
176 if (src->bitsPerPixel > 1)
177 fbCopyNto1(src, dst, gc, box, nbox, dx, dy,
178 reverse, upsidedown, bitplane, closure);
179 else
180 fbCopy1toN(src, dst, gc, box, nbox, dx, dy,
181 reverse, upsidedown, bitplane, closure);
182 } else {
183 fbCopyNtoN(src, dst, gc, box, nbox, dx, dy,
184 reverse, upsidedown, bitplane, closure);
187 glamor_finish_access(dst);
188 glamor_finish_access(src);
192 * Implements CopyPlane and CopyArea from the CPU to the GPU by using
193 * the source as a texture and painting that into the destination.
195 * This requires that source and dest are different textures, or that
196 * (if the copy area doesn't overlap), GL_NV_texture_barrier is used
197 * to ensure that the caches are flushed at the right times.
199 static Bool
200 glamor_copy_cpu_fbo(DrawablePtr src,
201 DrawablePtr dst,
202 GCPtr gc,
203 BoxPtr box,
204 int nbox,
205 int dx,
206 int dy,
207 Bool reverse,
208 Bool upsidedown,
209 Pixel bitplane,
210 void *closure)
212 ScreenPtr screen = dst->pScreen;
213 glamor_screen_private *glamor_priv = glamor_get_screen_private(screen);
214 PixmapPtr dst_pixmap = glamor_get_drawable_pixmap(dst);
215 int dst_xoff, dst_yoff;
217 if (gc && gc->alu != GXcopy)
218 goto bail;
220 if (gc && !glamor_pm_is_solid(gc->depth, gc->planemask))
221 goto bail;
223 glamor_make_current(glamor_priv);
225 if (!glamor_prepare_access(src, GLAMOR_ACCESS_RO))
226 goto bail;
228 glamor_get_drawable_deltas(dst, dst_pixmap, &dst_xoff, &dst_yoff);
230 if (bitplane) {
231 FbBits *tmp_bits;
232 FbStride tmp_stride;
233 int tmp_bpp;
234 int tmp_xoff, tmp_yoff;
236 PixmapPtr tmp_pix = fbCreatePixmap(screen, dst_pixmap->drawable.width,
237 dst_pixmap->drawable.height,
238 glamor_drawable_effective_depth(dst), 0);
240 if (!tmp_pix) {
241 glamor_finish_access(src);
242 goto bail;
245 tmp_pix->drawable.x = dst_xoff;
246 tmp_pix->drawable.y = dst_yoff;
248 fbGetDrawable(&tmp_pix->drawable, tmp_bits, tmp_stride, tmp_bpp, tmp_xoff,
249 tmp_yoff);
251 if (src->bitsPerPixel > 1)
252 fbCopyNto1(src, &tmp_pix->drawable, gc, box, nbox, dx, dy,
253 reverse, upsidedown, bitplane, closure);
254 else
255 fbCopy1toN(src, &tmp_pix->drawable, gc, box, nbox, dx, dy,
256 reverse, upsidedown, bitplane, closure);
258 glamor_upload_boxes(dst, box, nbox, tmp_xoff, tmp_yoff,
259 dst_xoff, dst_yoff, (uint8_t *) tmp_bits,
260 tmp_stride * sizeof(FbBits));
261 fbDestroyPixmap(tmp_pix);
262 } else {
263 FbBits *src_bits;
264 FbStride src_stride;
265 int src_bpp;
266 int src_xoff, src_yoff;
268 fbGetDrawable(src, src_bits, src_stride, src_bpp, src_xoff, src_yoff);
269 glamor_upload_boxes(dst, box, nbox, src_xoff + dx, src_yoff + dy,
270 dst_xoff, dst_yoff,
271 (uint8_t *) src_bits, src_stride * sizeof (FbBits));
273 glamor_finish_access(src);
275 return TRUE;
277 bail:
278 return FALSE;
282 * Implements CopyArea from the GPU to the CPU using glReadPixels from the
283 * source FBO.
285 static Bool
286 glamor_copy_fbo_cpu(DrawablePtr src,
287 DrawablePtr dst,
288 GCPtr gc,
289 BoxPtr box,
290 int nbox,
291 int dx,
292 int dy,
293 Bool reverse,
294 Bool upsidedown,
295 Pixel bitplane,
296 void *closure)
298 ScreenPtr screen = dst->pScreen;
299 glamor_screen_private *glamor_priv = glamor_get_screen_private(screen);
300 PixmapPtr src_pixmap = glamor_get_drawable_pixmap(src);
301 FbBits *dst_bits;
302 FbStride dst_stride;
303 int dst_bpp;
304 int src_xoff, src_yoff;
305 int dst_xoff, dst_yoff;
307 if (gc && gc->alu != GXcopy)
308 goto bail;
310 if (gc && !glamor_pm_is_solid(gc->depth, gc->planemask))
311 goto bail;
313 glamor_make_current(glamor_priv);
315 if (!glamor_prepare_access(dst, GLAMOR_ACCESS_RW))
316 goto bail;
318 glamor_get_drawable_deltas(src, src_pixmap, &src_xoff, &src_yoff);
320 fbGetDrawable(dst, dst_bits, dst_stride, dst_bpp, dst_xoff, dst_yoff);
322 glamor_download_boxes(src, box, nbox, src_xoff + dx, src_yoff + dy,
323 dst_xoff, dst_yoff,
324 (uint8_t *) dst_bits, dst_stride * sizeof (FbBits));
325 glamor_finish_access(dst);
327 return TRUE;
329 bail:
330 return FALSE;
333 /* Include the enums here for the moment, to keep from needing to bump epoxy. */
334 #ifndef GL_TILE_RASTER_ORDER_FIXED_MESA
335 #define GL_TILE_RASTER_ORDER_FIXED_MESA 0x8BB8
336 #define GL_TILE_RASTER_ORDER_INCREASING_X_MESA 0x8BB9
337 #define GL_TILE_RASTER_ORDER_INCREASING_Y_MESA 0x8BBA
338 #endif
341 * Copy from GPU to GPU by using the source
342 * as a texture and painting that into the destination
345 static Bool
346 glamor_copy_fbo_fbo_draw(DrawablePtr src,
347 DrawablePtr dst,
348 GCPtr gc,
349 BoxPtr box,
350 int nbox,
351 int dx,
352 int dy,
353 Bool reverse,
354 Bool upsidedown,
355 Pixel bitplane,
356 void *closure)
358 ScreenPtr screen = dst->pScreen;
359 glamor_screen_private *glamor_priv = glamor_get_screen_private(screen);
360 PixmapPtr src_pixmap = glamor_get_drawable_pixmap(src);
361 PixmapPtr dst_pixmap = glamor_get_drawable_pixmap(dst);
362 glamor_pixmap_private *src_priv = glamor_get_pixmap_private(src_pixmap);
363 glamor_pixmap_private *dst_priv = glamor_get_pixmap_private(dst_pixmap);
364 int src_box_index, dst_box_index;
365 int dst_off_x, dst_off_y;
366 int src_off_x, src_off_y;
367 GLshort *v;
368 char *vbo_offset;
369 struct copy_args args;
370 glamor_program *prog;
371 const glamor_facet *copy_facet;
372 int n;
373 Bool ret = FALSE;
374 BoxRec bounds = glamor_no_rendering_bounds();
376 glamor_make_current(glamor_priv);
378 if (gc && !glamor_set_planemask(gc->depth, gc->planemask))
379 goto bail_ctx;
381 if (!glamor_set_alu(dst, gc ? gc->alu : GXcopy))
382 goto bail_ctx;
384 if (bitplane && !glamor_priv->can_copyplane)
385 goto bail_ctx;
387 if (bitplane) {
388 prog = &glamor_priv->copy_plane_prog;
389 copy_facet = &glamor_facet_copyplane;
390 } else {
391 prog = &glamor_priv->copy_area_prog;
392 copy_facet = &glamor_facet_copyarea;
395 if (prog->failed)
396 goto bail_ctx;
398 if (!prog->prog) {
399 if (!glamor_build_program(screen, prog,
400 copy_facet, NULL, NULL, NULL))
401 goto bail_ctx;
404 args.src_drawable = src;
405 args.bitplane = bitplane;
407 /* Set up the vertex buffers for the points */
409 v = glamor_get_vbo_space(dst->pScreen, nbox * 8 * sizeof (int16_t), &vbo_offset);
411 if (src_pixmap == dst_pixmap && glamor_priv->has_mesa_tile_raster_order) {
412 glEnable(GL_TILE_RASTER_ORDER_FIXED_MESA);
413 if (dx >= 0)
414 glEnable(GL_TILE_RASTER_ORDER_INCREASING_X_MESA);
415 else
416 glDisable(GL_TILE_RASTER_ORDER_INCREASING_X_MESA);
417 if (dy >= 0)
418 glEnable(GL_TILE_RASTER_ORDER_INCREASING_Y_MESA);
419 else
420 glDisable(GL_TILE_RASTER_ORDER_INCREASING_Y_MESA);
423 glEnableVertexAttribArray(GLAMOR_VERTEX_POS);
424 glVertexAttribPointer(GLAMOR_VERTEX_POS, 2, GL_SHORT, GL_FALSE,
425 2 * sizeof (GLshort), vbo_offset);
427 if (nbox < 100) {
428 bounds = glamor_start_rendering_bounds();
429 for (int i = 0; i < nbox; i++)
430 glamor_bounds_union_box(&bounds, &box[i]);
433 for (n = 0; n < nbox; n++) {
434 v[0] = box->x1; v[1] = box->y1;
435 v[2] = box->x1; v[3] = box->y2;
436 v[4] = box->x2; v[5] = box->y2;
437 v[6] = box->x2; v[7] = box->y1;
439 v += 8;
440 box++;
443 glamor_put_vbo_space(screen);
445 glamor_get_drawable_deltas(src, src_pixmap, &src_off_x, &src_off_y);
447 glEnable(GL_SCISSOR_TEST);
449 glamor_pixmap_loop(src_priv, src_box_index) {
450 BoxPtr src_box = glamor_pixmap_box_at(src_priv, src_box_index);
452 args.dx = dx + src_off_x - src_box->x1;
453 args.dy = dy + src_off_y - src_box->y1;
454 args.src = glamor_pixmap_fbo_at(src_priv, src_box_index);
456 if (!glamor_use_program(dst, gc, prog, &args))
457 goto bail_ctx;
459 glamor_pixmap_loop(dst_priv, dst_box_index) {
460 BoxRec scissor = {
461 .x1 = max(-args.dx, bounds.x1),
462 .y1 = max(-args.dy, bounds.y1),
463 .x2 = min(-args.dx + src_box->x2 - src_box->x1, bounds.x2),
464 .y2 = min(-args.dy + src_box->y2 - src_box->y1, bounds.y2),
466 if (scissor.x1 >= scissor.x2 || scissor.y1 >= scissor.y2)
467 continue;
469 if (!glamor_set_destination_drawable(dst, dst_box_index, FALSE, FALSE,
470 prog->matrix_uniform,
471 &dst_off_x, &dst_off_y))
472 goto bail_ctx;
474 glScissor(scissor.x1 + dst_off_x,
475 scissor.y1 + dst_off_y,
476 scissor.x2 - scissor.x1,
477 scissor.y2 - scissor.y1);
479 glamor_glDrawArrays_GL_QUADS(glamor_priv, nbox);
483 ret = TRUE;
485 bail_ctx:
486 if (src_pixmap == dst_pixmap && glamor_priv->has_mesa_tile_raster_order) {
487 glDisable(GL_TILE_RASTER_ORDER_FIXED_MESA);
489 glDisable(GL_SCISSOR_TEST);
490 glDisableVertexAttribArray(GLAMOR_VERTEX_POS);
492 return ret;
496 * Copies from the GPU to the GPU using a temporary pixmap in between,
497 * to correctly handle overlapping copies.
500 static Bool
501 glamor_copy_fbo_fbo_temp(DrawablePtr src,
502 DrawablePtr dst,
503 GCPtr gc,
504 BoxPtr box,
505 int nbox,
506 int dx,
507 int dy,
508 Bool reverse,
509 Bool upsidedown,
510 Pixel bitplane,
511 void *closure)
513 ScreenPtr screen = dst->pScreen;
514 glamor_screen_private *glamor_priv = glamor_get_screen_private(screen);
515 PixmapPtr tmp_pixmap;
516 BoxRec bounds;
517 int n;
518 BoxPtr tmp_box;
520 if (nbox == 0)
521 return TRUE;
523 /* Sanity check state to avoid getting halfway through and bailing
524 * at the last second. Might be nice to have checks that didn't
525 * involve setting state.
527 glamor_make_current(glamor_priv);
529 if (gc && !glamor_set_planemask(gc->depth, gc->planemask))
530 goto bail_ctx;
532 if (!glamor_set_alu(dst, gc ? gc->alu : GXcopy))
533 goto bail_ctx;
535 /* Find the size of the area to copy
537 bounds = box[0];
538 for (n = 1; n < nbox; n++) {
539 bounds.x1 = min(bounds.x1, box[n].x1);
540 bounds.x2 = max(bounds.x2, box[n].x2);
541 bounds.y1 = min(bounds.y1, box[n].y1);
542 bounds.y2 = max(bounds.y2, box[n].y2);
545 /* Allocate a suitable temporary pixmap
547 tmp_pixmap = glamor_create_pixmap(screen,
548 bounds.x2 - bounds.x1,
549 bounds.y2 - bounds.y1,
550 glamor_drawable_effective_depth(src), 0);
551 if (!tmp_pixmap)
552 goto bail;
554 tmp_box = calloc(nbox, sizeof (BoxRec));
555 if (!tmp_box)
556 goto bail_pixmap;
558 /* Convert destination boxes into tmp pixmap boxes
560 for (n = 0; n < nbox; n++) {
561 tmp_box[n].x1 = box[n].x1 - bounds.x1;
562 tmp_box[n].x2 = box[n].x2 - bounds.x1;
563 tmp_box[n].y1 = box[n].y1 - bounds.y1;
564 tmp_box[n].y2 = box[n].y2 - bounds.y1;
567 if (!glamor_copy_fbo_fbo_draw(src,
568 &tmp_pixmap->drawable,
569 NULL,
570 tmp_box,
571 nbox,
572 dx + bounds.x1,
573 dy + bounds.y1,
574 FALSE, FALSE,
575 0, NULL))
576 goto bail_box;
578 if (!glamor_copy_fbo_fbo_draw(&tmp_pixmap->drawable,
579 dst,
581 box,
582 nbox,
583 -bounds.x1,
584 -bounds.y1,
585 FALSE, FALSE,
586 bitplane, closure))
587 goto bail_box;
589 free(tmp_box);
591 glamor_destroy_pixmap(tmp_pixmap);
593 return TRUE;
594 bail_box:
595 free(tmp_box);
596 bail_pixmap:
597 glamor_destroy_pixmap(tmp_pixmap);
598 bail:
599 return FALSE;
601 bail_ctx:
602 return FALSE;
606 * Returns TRUE if the copy has to be implemented with
607 * glamor_copy_fbo_fbo_temp() instead of glamor_copy_fbo_fbo().
609 * If the src and dst are in the same pixmap, then glamor_copy_fbo_fbo()'s
610 * sampling would give undefined results (since the same texture would be
611 * bound as an FBO destination and as a texture source). However, if we
612 * have GL_NV_texture_barrier, we can take advantage of the exception it
613 * added:
615 * "- If a texel has been written, then in order to safely read the result
616 * a texel fetch must be in a subsequent Draw separated by the command
618 * void TextureBarrierNV(void);
620 * TextureBarrierNV() will guarantee that writes have completed and caches
621 * have been invalidated before subsequent Draws are executed."
623 static Bool
624 glamor_copy_needs_temp(DrawablePtr src,
625 DrawablePtr dst,
626 BoxPtr box,
627 int nbox,
628 int dx,
629 int dy)
631 PixmapPtr src_pixmap = glamor_get_drawable_pixmap(src);
632 PixmapPtr dst_pixmap = glamor_get_drawable_pixmap(dst);
633 ScreenPtr screen = dst->pScreen;
634 glamor_screen_private *glamor_priv = glamor_get_screen_private(screen);
635 int n;
636 int dst_off_x, dst_off_y;
637 int src_off_x, src_off_y;
638 BoxRec bounds;
640 if (src_pixmap != dst_pixmap)
641 return FALSE;
643 if (nbox == 0)
644 return FALSE;
646 if (!glamor_priv->has_nv_texture_barrier)
647 return TRUE;
649 if (!glamor_priv->has_mesa_tile_raster_order) {
650 glamor_get_drawable_deltas(src, src_pixmap, &src_off_x, &src_off_y);
651 glamor_get_drawable_deltas(dst, dst_pixmap, &dst_off_x, &dst_off_y);
653 bounds = box[0];
654 for (n = 1; n < nbox; n++) {
655 bounds.x1 = min(bounds.x1, box[n].x1);
656 bounds.y1 = min(bounds.y1, box[n].y1);
658 bounds.x2 = max(bounds.x2, box[n].x2);
659 bounds.y2 = max(bounds.y2, box[n].y2);
662 /* Check to see if the pixmap-relative boxes overlap in both X and Y,
663 * in which case we can't rely on NV_texture_barrier and must
664 * make a temporary copy
666 * dst.x1 < src.x2 &&
667 * src.x1 < dst.x2 &&
669 * dst.y1 < src.y2 &&
670 * src.y1 < dst.y2
672 if (bounds.x1 + dst_off_x < bounds.x2 + dx + src_off_x &&
673 bounds.x1 + dx + src_off_x < bounds.x2 + dst_off_x &&
675 bounds.y1 + dst_off_y < bounds.y2 + dy + src_off_y &&
676 bounds.y1 + dy + src_off_y < bounds.y2 + dst_off_y) {
677 return TRUE;
681 glTextureBarrierNV();
683 return FALSE;
686 static Bool
687 glamor_copy_gl(DrawablePtr src,
688 DrawablePtr dst,
689 GCPtr gc,
690 BoxPtr box,
691 int nbox,
692 int dx,
693 int dy,
694 Bool reverse,
695 Bool upsidedown,
696 Pixel bitplane,
697 void *closure)
699 PixmapPtr src_pixmap = glamor_get_drawable_pixmap(src);
700 PixmapPtr dst_pixmap = glamor_get_drawable_pixmap(dst);
701 glamor_pixmap_private *src_priv = glamor_get_pixmap_private(src_pixmap);
702 glamor_pixmap_private *dst_priv = glamor_get_pixmap_private(dst_pixmap);
704 if (GLAMOR_PIXMAP_PRIV_HAS_FBO(dst_priv)) {
705 if (GLAMOR_PIXMAP_PRIV_HAS_FBO(src_priv)) {
706 if (glamor_copy_needs_temp(src, dst, box, nbox, dx, dy))
707 return glamor_copy_fbo_fbo_temp(src, dst, gc, box, nbox, dx, dy,
708 reverse, upsidedown, bitplane, closure);
709 else
710 return glamor_copy_fbo_fbo_draw(src, dst, gc, box, nbox, dx, dy,
711 reverse, upsidedown, bitplane, closure);
714 return glamor_copy_cpu_fbo(src, dst, gc, box, nbox, dx, dy,
715 reverse, upsidedown, bitplane, closure);
716 } else if (GLAMOR_PIXMAP_PRIV_HAS_FBO(src_priv) &&
717 dst_priv->type != GLAMOR_DRM_ONLY &&
718 bitplane == 0) {
719 return glamor_copy_fbo_cpu(src, dst, gc, box, nbox, dx, dy,
720 reverse, upsidedown, bitplane, closure);
722 return FALSE;
725 void
726 glamor_copy(DrawablePtr src,
727 DrawablePtr dst,
728 GCPtr gc,
729 BoxPtr box,
730 int nbox,
731 int dx,
732 int dy,
733 Bool reverse,
734 Bool upsidedown,
735 Pixel bitplane,
736 void *closure)
738 if (nbox == 0)
739 return;
741 if (glamor_copy_gl(src, dst, gc, box, nbox, dx, dy, reverse, upsidedown, bitplane, closure))
742 return;
743 glamor_copy_bail(src, dst, gc, box, nbox, dx, dy, reverse, upsidedown, bitplane, closure);
746 RegionPtr
747 glamor_copy_area(DrawablePtr src, DrawablePtr dst, GCPtr gc,
748 int srcx, int srcy, int width, int height, int dstx, int dsty)
750 return miDoCopy(src, dst, gc,
751 srcx, srcy, width, height,
752 dstx, dsty, glamor_copy, 0, NULL);
755 RegionPtr
756 glamor_copy_plane(DrawablePtr src, DrawablePtr dst, GCPtr gc,
757 int srcx, int srcy, int width, int height, int dstx, int dsty,
758 unsigned long bitplane)
760 if ((bitplane & FbFullMask(glamor_drawable_effective_depth(src))) == 0)
761 return miHandleExposures(src, dst, gc,
762 srcx, srcy, width, height, dstx, dsty);
763 return miDoCopy(src, dst, gc,
764 srcx, srcy, width, height,
765 dstx, dsty, glamor_copy, bitplane, NULL);
768 void
769 glamor_copy_window(WindowPtr window, DDXPointRec old_origin, RegionPtr src_region)
771 PixmapPtr pixmap = glamor_get_drawable_pixmap(&window->drawable);
772 DrawablePtr drawable = &pixmap->drawable;
773 RegionRec dst_region;
774 int dx, dy;
776 dx = old_origin.x - window->drawable.x;
777 dy = old_origin.y - window->drawable.y;
778 RegionTranslate(src_region, -dx, -dy);
780 RegionNull(&dst_region);
782 RegionIntersect(&dst_region, &window->borderClip, src_region);
784 #if defined(COMPOSITE) || defined(ROOTLESS)
785 if (pixmap->screen_x || pixmap->screen_y)
786 RegionTranslate(&dst_region, -pixmap->screen_x, -pixmap->screen_y);
787 #endif
789 miCopyRegion(drawable, drawable,
790 0, &dst_region, dx, dy, glamor_copy, 0, 0);
792 RegionUninit(&dst_region);