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
23 #include "glamor_priv.h"
24 #include "glamor_transfer.h"
25 #include "glamor_prepare.h"
26 #include "glamor_transform.h"
29 DrawablePtr src_drawable
;
30 glamor_pixmap_fbo
*src
;
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
);
50 static const glamor_facet glamor_facet_copyarea
= {
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
,
61 * Configure the copy plane program for the current operation
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
)) {
82 glUniform4ui(prog
->bitplane_uniform
,
83 (args
->bitplane
>> 20) & 0x3ff,
84 (args
->bitplane
>> 10) & 0x3ff,
85 (args
->bitplane
) & 0x3ff,
88 glUniform4f(prog
->bitmul_uniform
, 0x3ff, 0x3ff, 0x3ff, 0);
91 glUniform4ui(prog
->bitplane_uniform
,
92 (args
->bitplane
>> 16) & 0xff,
93 (args
->bitplane
>> 8) & 0xff,
94 (args
->bitplane
) & 0xff,
97 glUniform4f(prog
->bitmul_uniform
, 0xff, 0xff, 0xff, 0);
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);
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);
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);
127 glUniform4ui(prog
->bitplane_uniform
,
128 0, 0, 0, args
->bitplane
);
129 glUniform4f(prog
->bitmul_uniform
, 0, 0, 0, 0xff);
132 glUniform4ui(prog
->bitplane_uniform
,
133 0, 0, 0, args
->bitplane
);
134 glUniform4f(prog
->bitmul_uniform
, 0, 0, 0, 0xff);
141 static const glamor_facet glamor_facet_copyplane
= {
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"
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
162 glamor_copy_bail(DrawablePtr src
,
174 if (glamor_prepare_access(dst
, GLAMOR_ACCESS_RW
) && glamor_prepare_access(src
, GLAMOR_ACCESS_RO
)) {
176 if (src
->bitsPerPixel
> 1)
177 fbCopyNto1(src
, dst
, gc
, box
, nbox
, dx
, dy
,
178 reverse
, upsidedown
, bitplane
, closure
);
180 fbCopy1toN(src
, dst
, gc
, box
, nbox
, dx
, dy
,
181 reverse
, upsidedown
, bitplane
, closure
);
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.
200 glamor_copy_cpu_fbo(DrawablePtr src
,
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
)
220 if (gc
&& !glamor_pm_is_solid(gc
->depth
, gc
->planemask
))
223 glamor_make_current(glamor_priv
);
225 if (!glamor_prepare_access(src
, GLAMOR_ACCESS_RO
))
228 glamor_get_drawable_deltas(dst
, dst_pixmap
, &dst_xoff
, &dst_yoff
);
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);
241 glamor_finish_access(src
);
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
,
251 if (src
->bitsPerPixel
> 1)
252 fbCopyNto1(src
, &tmp_pix
->drawable
, gc
, box
, nbox
, dx
, dy
,
253 reverse
, upsidedown
, bitplane
, closure
);
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
);
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
,
271 (uint8_t *) src_bits
, src_stride
* sizeof (FbBits
));
273 glamor_finish_access(src
);
282 * Implements CopyArea from the GPU to the CPU using glReadPixels from the
286 glamor_copy_fbo_cpu(DrawablePtr src
,
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
);
304 int src_xoff
, src_yoff
;
305 int dst_xoff
, dst_yoff
;
307 if (gc
&& gc
->alu
!= GXcopy
)
310 if (gc
&& !glamor_pm_is_solid(gc
->depth
, gc
->planemask
))
313 glamor_make_current(glamor_priv
);
315 if (!glamor_prepare_access(dst
, GLAMOR_ACCESS_RW
))
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
,
324 (uint8_t *) dst_bits
, dst_stride
* sizeof (FbBits
));
325 glamor_finish_access(dst
);
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
341 * Copy from GPU to GPU by using the source
342 * as a texture and painting that into the destination
346 glamor_copy_fbo_fbo_draw(DrawablePtr src
,
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
;
369 struct copy_args args
;
370 glamor_program
*prog
;
371 const glamor_facet
*copy_facet
;
374 BoxRec bounds
= glamor_no_rendering_bounds();
376 glamor_make_current(glamor_priv
);
378 if (gc
&& !glamor_set_planemask(gc
->depth
, gc
->planemask
))
381 if (!glamor_set_alu(dst
, gc
? gc
->alu
: GXcopy
))
384 if (bitplane
&& !glamor_priv
->can_copyplane
)
388 prog
= &glamor_priv
->copy_plane_prog
;
389 copy_facet
= &glamor_facet_copyplane
;
391 prog
= &glamor_priv
->copy_area_prog
;
392 copy_facet
= &glamor_facet_copyarea
;
399 if (!glamor_build_program(screen
, prog
,
400 copy_facet
, NULL
, NULL
, NULL
))
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
);
414 glEnable(GL_TILE_RASTER_ORDER_INCREASING_X_MESA
);
416 glDisable(GL_TILE_RASTER_ORDER_INCREASING_X_MESA
);
418 glEnable(GL_TILE_RASTER_ORDER_INCREASING_Y_MESA
);
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
);
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
;
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
))
459 glamor_pixmap_loop(dst_priv
, dst_box_index
) {
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
)
469 if (!glamor_set_destination_drawable(dst
, dst_box_index
, FALSE
, FALSE
,
470 prog
->matrix_uniform
,
471 &dst_off_x
, &dst_off_y
))
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
);
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
);
496 * Copies from the GPU to the GPU using a temporary pixmap in between,
497 * to correctly handle overlapping copies.
501 glamor_copy_fbo_fbo_temp(DrawablePtr src
,
513 ScreenPtr screen
= dst
->pScreen
;
514 glamor_screen_private
*glamor_priv
= glamor_get_screen_private(screen
);
515 PixmapPtr tmp_pixmap
;
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
))
532 if (!glamor_set_alu(dst
, gc
? gc
->alu
: GXcopy
))
535 /* Find the size of the area to copy
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);
554 tmp_box
= calloc(nbox
, sizeof (BoxRec
));
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
,
578 if (!glamor_copy_fbo_fbo_draw(&tmp_pixmap
->drawable
,
591 glamor_destroy_pixmap(tmp_pixmap
);
597 glamor_destroy_pixmap(tmp_pixmap
);
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
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."
624 glamor_copy_needs_temp(DrawablePtr src
,
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
);
636 int dst_off_x
, dst_off_y
;
637 int src_off_x
, src_off_y
;
640 if (src_pixmap
!= dst_pixmap
)
646 if (!glamor_priv
->has_nv_texture_barrier
)
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
);
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
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
) {
681 glTextureBarrierNV();
687 glamor_copy_gl(DrawablePtr src
,
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
);
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
&&
719 return glamor_copy_fbo_cpu(src
, dst
, gc
, box
, nbox
, dx
, dy
,
720 reverse
, upsidedown
, bitplane
, closure
);
726 glamor_copy(DrawablePtr src
,
741 if (glamor_copy_gl(src
, dst
, gc
, box
, nbox
, dx
, dy
, reverse
, upsidedown
, bitplane
, closure
))
743 glamor_copy_bail(src
, dst
, gc
, box
, nbox
, dx
, dy
, reverse
, upsidedown
, bitplane
, closure
);
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
);
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
);
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
;
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
);
789 miCopyRegion(drawable
, drawable
,
790 0, &dst_region
, dx
, dy
, glamor_copy
, 0, 0);
792 RegionUninit(&dst_region
);