2 _cairo_gpu_destination_idx_drawable(cairo_gpu_surface_t
* surface
)
8 _cairo_gpu_destination_idx_msaa(cairo_gpu_surface_t
* surface
, int want_msaa
)
14 _cairo_gpu_destination_idx(cairo_gpu_surface_t
* surface
)
16 return _cairo_gpu_destination_idx_msaa(surface
, surface
->want_msaa
);
19 static inline cairo_bool_t
20 _cairo_gpu_surface_has_physical_alpha(cairo_gpu_surface_t
* surface
)
22 // We assume that the unused alpha channel is set to 1
23 // TODO: due to this, we don't try to use the alpha channels of drawables; check whether we can do something about this
27 static inline cairo_gpu_context_t
*
28 _cairo_gpu_surface_lookup_context(cairo_gpu_surface_t
* surface
)
30 return _cairo_gpu_space_lookup_context(surface
->space
);
34 _cairo_gpu_surface_use_msaa(cairo_gpu_surface_t
* surface
)
41 _cairo_gpu_surface_create_tex(cairo_gpu_context_t
* ctx
, cairo_gpu_surface_t
* surface
)
43 // NO: unsigned format = (surface->base.content == CAIRO_CONTENT_COLOR) ? GL_RGB : GL_RGBA;
44 // we must have an alpha channel to support EXTEND_NONE (and we also assume it exists to draw trapezoid masks)
45 _cairo_gpu_texture_realize(ctx
, &surface
->texture
);
49 _cairo_gpu_context_set_surface(cairo_gpu_context_t
* ctx
, int mask
, cairo_gpu_surface_t
* surface
, int i
)
53 if(!surface
->texture
.texture
)
54 _cairo_gpu_surface_create_tex(ctx
, surface
);
58 ctx
->read_surface
= surface
->texture
.surface
;
59 ctx
->read_texture
= &surface
->texture
;
63 _cairo_gallium_context_set_framebuffer(ctx
, surface
->texture
.surface
, surface
->width
, surface
->height
);
71 _cairo_gpu_blit_image(cairo_gpu_context_t
* ctx
, cairo_gpu_surface_t
* dst
, cairo_gpu_texture_t
* texture
, int dst_x
, int dst_y
, int src_x
, int src_y
, int width
, int height
, int zoom_x
, int zoom_y
);
74 _cairo_gpu_clear_(cairo_gpu_context_t
* ctx
, cairo_gpu_surface_t
* surface
, int i
);
76 static __attribute__((unused
)) void
77 _cairo_gpu_fill_rect_diff(cairo_gpu_context_t
* ctx
, cairo_gpu_surface_t
* surface
, cairo_rectangle_int_t
* out
, cairo_rectangle_int_t
* in
, float r
, float g
, float b
, float a
);
79 // may clobber read fbo and draw state
81 _cairo_gpu_surface_do_update(cairo_gpu_context_t
* ctx
, cairo_gpu_surface_t
* surface
, int j
)
83 assert(!(surface
->valid_mask
& (1 << j
)));
86 ctx
= _cairo_gpu_surface_get_bind_context(surface
);
90 if(!surface
->texture
.texture
)
91 _cairo_gpu_surface_create_tex(ctx
, surface
);
94 for(i = 0; i < 4; ++i)
96 if(surface->valid_mask & (1 << i))
98 cairo_rectangle_int_t *out = &surface->bbox[j];
99 cairo_rectangle_int_t *in = &surface->bbox[i];
101 _cairo_gpu_fill_rect_diff(ctx, surface, out, in, 0, 0, 0, 0);
103 _cairo_gpu_context_set_surface(ctx, FB_READ, surface, i);
105 //printf("blit %i to %i: (%i, %i, %i, %i) -> (%i, %i, %i, %i)\n", i, j, in->x, in->y, in->width, in->height, out->x, out->y, out->width, out->height);
106 //_cairo_gpu_context_fill_rect(ctx, out->x, out->y, out->width, out->height, 0, 0, 0, 0);
108 _cairo_gpu_context_blit_same(ctx, surface, in->x, in->y, in->width, in->height);
110 memcpy(out, in, sizeof(*in));
117 cairo_rectangle_int_t
*box
= &surface
->bbox
[j
];
119 if(surface
->base
.content
== CAIRO_CONTENT_COLOR
)
120 _cairo_gpu_context_fill_rect_unbound(ctx
, surface
, box
->x
, box
->y
, box
->width
, box
->height
, 0, 0, 0, 1);
122 _cairo_gpu_context_fill_rect_unbound(ctx
, surface
, box
->x
, box
->y
, box
->width
, box
->height
, 0, 0, 0, 0);
128 surface
->valid_mask
|= 1 << j
;
132 _cairo_gpu_begin_write(cairo_gpu_context_t
* ctx
, cairo_gpu_surface_t
* surface
)
134 int idx
= _cairo_gpu_destination_idx(surface
);
135 if(!(surface
->valid_mask
& (1 << idx
)))
136 _cairo_gpu_surface_do_update(ctx
, surface
, idx
);
137 _cairo_gpu_context_set_surface(ctx
, FB_DRAW
, surface
, idx
);
141 _cairo_gpu_begin_read_write(cairo_gpu_context_t
* ctx
, cairo_gpu_surface_t
* surface
)
143 int idx
= _cairo_gpu_destination_idx(surface
);
144 if(!(surface
->valid_mask
& (1 << idx
)))
145 _cairo_gpu_surface_do_update(ctx
, surface
, idx
);
147 _cairo_gpu_context_set_surface(ctx
, FB_DRAW
| FB_READ
, surface
, idx
);
150 static void _cairo_gpu_end_modify(cairo_gpu_context_t
* ctx
, cairo_gpu_surface_t
* surface
, int idx
)
152 surface
->valid_mask
= 1 << idx
;
156 _cairo_gpu_end_write(cairo_gpu_context_t
* ctx
, cairo_gpu_surface_t
* surface
)
158 _cairo_gpu_end_modify(ctx
, surface
, _cairo_gpu_destination_idx(surface
));
162 _cairo_gpu_end_write_nomodify(cairo_gpu_context_t
* ctx
, cairo_gpu_surface_t
* surface
)
166 static __attribute__((unused
)) void
167 _cairo_gpu_end_read_write(cairo_gpu_context_t
* ctx
, cairo_gpu_surface_t
* surface
)
169 _cairo_gpu_end_modify(ctx
, surface
, _cairo_gpu_destination_idx(surface
));
173 _cairo_gpu_end_read_write_nomodify(cairo_gpu_context_t
* ctx
, cairo_gpu_surface_t
* surface
)
178 _cairo_gpu_begin_read(cairo_gpu_context_t
* ctx
, cairo_gpu_surface_t
* surface
)
180 int idx
= _cairo_gpu_destination_idx(surface
);
181 if(!(surface
->valid_mask
& (1 << idx
)))
182 _cairo_gpu_surface_do_update(ctx
, surface
, idx
);
184 _cairo_gpu_context_set_surface(ctx
, FB_READ
, surface
, idx
);
188 _cairo_gpu_end_read(cairo_gpu_context_t
* ctx
, cairo_gpu_surface_t
* surface
)
192 // TODO: maybe we want to generate mipmaps?
193 // may clobber read fb, blend/color mask
194 // this binds the texture
195 static inline cairo_gpu_texture_t
*
196 _cairo_gpu_begin_tex(cairo_gpu_context_t
* ctx
, cairo_gpu_surface_t
* dst
, int i
, cairo_gpu_surface_t
* surface
)
198 if(!(surface
->valid_mask
& (1 << SURF_TEX
)))
201 ctx
= _cairo_gpu_surface_get_bind_context(surface
);
203 _cairo_gpu_surface_do_update(ctx
, surface
, SURF_TEX
);
207 if(!(surface
->valid_mask
& (1 << SURF_PSEUDO_MIPMAPS
)) && !surface
->tex_rectangle
)
212 return &surface
->texture
;
216 _cairo_gpu_end_tex(cairo_gpu_context_t
* ctx
, cairo_gpu_surface_t
* surface
, cairo_gpu_texture_t
* texture
)
220 static int _cairo_gpu_aa_formats
[] = {
230 static cairo_int_status_t
231 _cairo_gpu_surface_set_samples(void* abstract_surface
, unsigned coverage_samples
, unsigned color_samples
)
233 // TODO: implement this
234 return CAIRO_STATUS_NO_MEMORY
;
237 static cairo_surface_t
*
238 _cairo_gpu_surface_create(void * abstract_space
, void* abstract_surface
, cairo_content_t content
, unsigned long drawable
, unsigned long visualid
, cairo_bool_t double_buffer
, double width
, double height
, int color_mantissa_bits
, int alpha_mantissa_bits
, int exponent_bits
, int shared_exponent_bits
)
240 cairo_gpu_space_t
* space
= abstract_space
;
241 cairo_gpu_surface_t
* surface
= abstract_surface
;
243 if(surface
&& surface
->base
.backend
!= &_cairo_gpu_surface_backend
)
244 return _cairo_surface_create_in_error(CAIRO_STATUS_SURFACE_TYPE_MISMATCH
);
249 return _cairo_surface_create_in_error(CAIRO_STATUS_SURFACE_FINISHED
);
251 space
= surface
->space
;
257 return _cairo_surface_create_in_error(CAIRO_STATUS_SURFACE_FINISHED
);
258 width
= surface
->width
;
264 return _cairo_surface_create_in_error(CAIRO_STATUS_SURFACE_FINISHED
);
265 height
= surface
->height
;
269 return _cairo_surface_create_in_error(CAIRO_STATUS_SURFACE_TYPE_MISMATCH
);
272 _cairo_gpu_texture_fini(0, &surface
->texture
);
275 surface
= calloc(1, sizeof(cairo_gpu_surface_t
));
276 if(unlikely(surface
== NULL
))
277 return (cairo_surface_t
*)_cairo_surface_create_in_error(_cairo_error(CAIRO_STATUS_NO_MEMORY
));
279 _cairo_surface_init(&surface
->base
, &_cairo_gpu_surface_backend
, 0);
287 surface
->width
= width
;
288 surface
->height
= height
;
289 surface
->base
.content
= content
;
290 surface
->space
= (cairo_gpu_space_t
*)cairo_space_reference(&space
->base
);
292 _cairo_gpu_texture_init(space
, &surface
->texture
, width
, height
);
294 // uninitialized, so set fully dirty
295 surface
->bbox
[SURF_TEX
].x
= 0;
296 surface
->bbox
[SURF_TEX
].y
= 0;
297 surface
->bbox
[SURF_TEX
].width
= surface
->width
;
298 surface
->bbox
[SURF_TEX
].height
= surface
->height
;
299 surface
->valid_mask
= 0;
300 return &surface
->base
;
304 _cairo_gpu_dirty_rect_(cairo_gpu_surface_t
* surface
, int i
, int x
, int y
, int width
, int height
);
306 static cairo_status_t
307 _cairo_gpu_surface_swap_page(void* abstract_surface
)
309 return CAIRO_STATUS_SUCCESS
;
312 static cairo_int_status_t
313 _cairo_gpu_surface_copy_page(void *abstract_surface
)
315 return CAIRO_STATUS_SUCCESS
;
319 _cairo_gpu_begin_read(cairo_gpu_context_t
* ctx
, cairo_gpu_surface_t
* surface
);
322 _cairo_gpu_end_read(cairo_gpu_context_t
* ctx
, cairo_gpu_surface_t
* surface
);
324 static cairo_status_t
325 _cairo_gpu_surface_get_image(cairo_gpu_surface_t
* surface
, cairo_rectangle_int_t
* interest
, cairo_image_surface_t
** image_out
, cairo_rectangle_int_t
* rect_out
, void** extra
)
327 struct pipe_transfer
* transfer
;
329 cairo_image_surface_t
* image
;
330 cairo_gpu_context_t
* ctx
;
331 pixman_format_code_t pixman_format
;
333 ctx
= _cairo_gpu_space_get_bind_context(surface
->space
);
335 if(!(surface
->valid_mask
& (1 << SURF_TEX
)))
336 _cairo_gpu_surface_do_update(ctx
, surface
, SURF_TEX
);
338 if(ctx
->pipe
->is_texture_referenced(ctx
->pipe
, surface
->texture
.texture
, 0, 0) & PIPE_REFERENCED_FOR_WRITE
)
340 struct pipe_fence_handle
* fence
;
341 ctx
->pipe
->flush(ctx
->pipe
, PIPE_FLUSH_RENDER_CACHE
, &fence
);
345 ctx
->space
->screen
->fence_finish(ctx
->space
->screen
, fence
, 0);
346 ctx
->space
->screen
->fence_reference(ctx
->space
->screen
, &fence
, 0);
350 transfer
= surface
->space
->screen
->get_tex_transfer(surface
->space
->screen
, surface
->texture
.texture
, 0, 0, 0, PIPE_TRANSFER_WRITE
, interest
? interest
->x
: 0, interest
? interest
->y
: 0, interest
? interest
->width
: (int)surface
->width
, interest
? interest
->height
: (int)surface
->height
);
351 data
= surface
->space
->screen
->transfer_map(surface
->space
->screen
, transfer
);
353 if(transfer
->format
== PIPE_FORMAT_A8R8G8B8_UNORM
)
355 if(surface
->base
.content
== CAIRO_CONTENT_COLOR
)
356 pixman_format
= PIXMAN_x8r8g8b8
;
358 pixman_format
= PIXMAN_a8r8g8b8
;
363 image
= (cairo_image_surface_t
*)_cairo_image_surface_create_with_pixman_format (data
, pixman_format
, interest
? interest
->width
: (int)surface
->width
, interest
? interest
->height
: (int)surface
->height
, transfer
->stride
);
364 if(image
->base
.status
)
365 return image
->base
.status
;
370 *rect_out
= *interest
;
375 rect_out
->width
= surface
->width
;
376 rect_out
->width
= surface
->height
;
382 return CAIRO_STATUS_SUCCESS
;
385 static cairo_status_t
386 _cairo_gpu_surface_put_image(cairo_gpu_surface_t
* dst
, cairo_image_surface_t
* src
, int src_x
, int src_y
, int width
, int height
, int dst_x
, int dst_y
, int is_write
, void* extra
)
388 struct pipe_transfer
* transfer
= (struct pipe_transfer
*)extra
;
389 dst
->space
->screen
->transfer_unmap(dst
->space
->screen
, transfer
);
390 dst
->space
->screen
->tex_transfer_destroy(transfer
);
391 return CAIRO_STATUS_SUCCESS
;
395 _cairo_gpu_dirty_rect(cairo_gpu_surface_t
* surface
, int x
, int y
, int width
, int height
);
397 static cairo_status_t
398 _cairo_gpu_surface_draw_image(cairo_gpu_surface_t
* dst
, cairo_image_surface_t
* src
, int src_x
, int src_y
, int width
, int height
, int dst_x
, int dst_y
)
400 cairo_gpu_context_t
* ctx
= _cairo_gpu_space_get_bind_context(dst
->space
);
401 if(!(dst
->valid_mask
& (1 << SURF_TEX
)))
403 if(dst_x
== 0 && dst_y
== 0 && width
== (int)dst
->width
&& height
== (int)dst
->height
)
405 if(!dst
->texture
.texture
)
406 _cairo_gpu_surface_create_tex(ctx
, dst
);
409 _cairo_gpu_surface_do_update(ctx
, dst
, SURF_TEX
);
412 _cairo_gpu_context_upload_pixels(ctx
, dst
, -1, &dst
->texture
, src
, src_x
, src_y
, width
, height
, dst_x
, dst_y
);
413 _cairo_gpu_dirty_rect(dst
, dst_x
, dst_y
, width
, height
);
414 _cairo_gpu_end_modify(ctx
, dst
, SURF_TEX
);
415 return CAIRO_STATUS_SUCCESS
;
418 static cairo_status_t
419 _cairo_gpu_surface_finish(void *abstract_surface
)
421 cairo_gpu_surface_t
*surface
= abstract_surface
;
422 cairo_gpu_space_t
* space
= surface
->space
;
424 _cairo_gpu_surface_set_samples(surface
, 0, 0);
426 _cairo_gpu_texture_fini(0, &surface
->texture
);
428 cairo_space_destroy(&space
->base
);
430 return CAIRO_STATUS_SUCCESS
;
434 _cairo_gpu_clear(cairo_gpu_context_t
* ctx
, cairo_gpu_surface_t
* surface
);
437 cairo_gallium_surface_get_texture(cairo_surface_t
* abstract_surface
)
439 cairo_gpu_surface_t
* surface
= (cairo_gpu_surface_t
*)abstract_surface
;
440 if(abstract_surface
->backend
!= &_cairo_gpu_surface_backend
)
443 if(!surface
->texture
.texture
)
444 _cairo_gpu_surface_create_tex(0, surface
);
446 return surface
->texture
.texture
;
450 _cairo_gpu_surface_orient_drawable_like_texture(cairo_gpu_surface_t
* draw_surf
, cairo_gpu_surface_t
* tex_surf
)