Add stubs for Direct3D9 backend.
[cairo/gpu.git] / src / gpu / cairo-gpu-impl-surface-gallium.h
blob935270a9b09d59d91b6703beb45c171b2cac8010
1 static inline int
2 _cairo_gpu_destination_idx_drawable(cairo_gpu_surface_t * surface)
4 return -1;
7 static inline int
8 _cairo_gpu_destination_idx_msaa(cairo_gpu_surface_t * surface, int want_msaa)
10 return SURF_TEX;
13 static inline int
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
24 return TRUE;
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);
33 static inline int
34 _cairo_gpu_surface_use_msaa(cairo_gpu_surface_t * surface)
36 return 0;
40 static void
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);
48 static void
49 _cairo_gpu_context_set_surface(cairo_gpu_context_t* ctx, int mask, cairo_gpu_surface_t * surface, int i)
51 if(i == SURF_TEX)
53 if(!surface->texture.texture)
54 _cairo_gpu_surface_create_tex(ctx, surface);
56 if(mask & FB_READ)
58 ctx->read_surface = surface->texture.surface;
59 ctx->read_texture = &surface->texture;
62 if(mask & FB_DRAW)
63 _cairo_gallium_context_set_framebuffer(ctx, surface->texture.surface, surface->width, surface->height);
65 else
66 assert(0);
70 static void
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);
73 static void
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
80 static void
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)));
85 if(!ctx)
86 ctx = _cairo_gpu_surface_get_bind_context(surface);
88 if(j == SURF_TEX)
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));
111 goto out;
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);
121 else
122 _cairo_gpu_context_fill_rect_unbound(ctx, surface, box->x, box->y, box->width, box->height, 0, 0, 0, 0);
124 box->width = 0;
125 box->height = 0;
128 surface->valid_mask |= 1 << j;
131 static inline void
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);
140 static inline void
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;
155 static void
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));
161 static void
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));
172 static void
173 _cairo_gpu_end_read_write_nomodify(cairo_gpu_context_t * ctx, cairo_gpu_surface_t* surface)
177 static inline void
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);
187 static inline void
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)))
200 if(!ctx)
201 ctx = _cairo_gpu_surface_get_bind_context(surface);
203 _cairo_gpu_surface_do_update(ctx, surface, SURF_TEX);
206 #if 0
207 if(!(surface->valid_mask & (1 << SURF_PSEUDO_MIPMAPS)) && !surface->tex_rectangle)
209 assert(0); // TODO
211 #endif
212 return &surface->texture;
215 static void
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[] = {
221 16, 4,
222 16, 8,
223 16, 16,
224 8, 4,
225 8, 8,
226 4, 4, // 4x MSAA
227 0, 0
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);
246 if(!space)
248 if(!surface)
249 return _cairo_surface_create_in_error(CAIRO_STATUS_SURFACE_FINISHED);
251 space = surface->space;
254 if(width < 0)
256 if(!surface)
257 return _cairo_surface_create_in_error(CAIRO_STATUS_SURFACE_FINISHED);
258 width = surface->width;
261 if(height < 0)
263 if(!surface)
264 return _cairo_surface_create_in_error(CAIRO_STATUS_SURFACE_FINISHED);
265 height = surface->height;
268 if(drawable)
269 return _cairo_surface_create_in_error(CAIRO_STATUS_SURFACE_TYPE_MISMATCH);
271 if(surface)
272 _cairo_gpu_texture_fini(0, &surface->texture);
273 else
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);
282 if(width < 1)
283 width = 1;
284 if(height < 1)
285 height = 1;
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;
303 static inline void
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;
318 static inline void
319 _cairo_gpu_begin_read(cairo_gpu_context_t* ctx, cairo_gpu_surface_t * surface);
321 static inline void
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;
328 unsigned char* data;
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);
343 if(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;
357 else
358 pixman_format = PIXMAN_a8r8g8b8;
360 else
361 abort();
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;
367 if(rect_out)
369 if(interest)
370 *rect_out = *interest;
371 else
373 rect_out->x = 0;
374 rect_out->y = 0;
375 rect_out->width = surface->width;
376 rect_out->width = surface->height;
379 *image_out = image;
380 *extra = transfer;
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;
394 static inline void
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);
408 else
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;
433 static void
434 _cairo_gpu_clear(cairo_gpu_context_t* ctx, cairo_gpu_surface_t * surface);
436 struct pipe_texture*
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)
441 return 0;
443 if(!surface->texture.texture)
444 _cairo_gpu_surface_create_tex(0, surface);
446 return surface->texture.texture;
449 static inline void
450 _cairo_gpu_surface_orient_drawable_like_texture(cairo_gpu_surface_t* draw_surf, cairo_gpu_surface_t* tex_surf)