457f678a5c74a354acaa51820f59ced0cd4b77bc
[mesa.git] / src / gallium / state_trackers / vdpau / output.c
1 /**************************************************************************
2 *
3 * Copyright 2010 Thomas Balling Sørensen.
4 * Copyright 2011 Christian König.
5 * All Rights Reserved.
6 *
7 * Permission is hereby granted, free of charge, to any person obtaining a
8 * copy of this software and associated documentation files (the
9 * "Software"), to deal in the Software without restriction, including
10 * without limitation the rights to use, copy, modify, merge, publish,
11 * distribute, sub license, and/or sell copies of the Software, and to
12 * permit persons to whom the Software is furnished to do so, subject to
13 * the following conditions:
14 *
15 * The above copyright notice and this permission notice (including the
16 * next paragraph) shall be included in all copies or substantial portions
17 * of the Software.
18 *
19 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
20 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
21 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
22 * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR
23 * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
24 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
25 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
26 *
27 **************************************************************************/
28
29 #include <vdpau/vdpau.h>
30
31 #include "util/u_debug.h"
32 #include "util/u_memory.h"
33 #include "util/u_sampler.h"
34 #include "util/u_format.h"
35 #include "util/u_surface.h"
36
37 #include "vl/vl_csc.h"
38
39 #include "vdpau_private.h"
40
41 /**
42 * Create a VdpOutputSurface.
43 */
44 VdpStatus
45 vlVdpOutputSurfaceCreate(VdpDevice device,
46 VdpRGBAFormat rgba_format,
47 uint32_t width, uint32_t height,
48 VdpOutputSurface *surface)
49 {
50 struct pipe_context *pipe;
51 struct pipe_resource res_tmpl, *res;
52 struct pipe_sampler_view sv_templ;
53 struct pipe_surface surf_templ;
54
55 vlVdpOutputSurface *vlsurface = NULL;
56
57 if (!(width && height))
58 return VDP_STATUS_INVALID_SIZE;
59
60 vlVdpDevice *dev = vlGetDataHTAB(device);
61 if (!dev)
62 return VDP_STATUS_INVALID_HANDLE;
63
64 pipe = dev->context;
65 if (!pipe)
66 return VDP_STATUS_INVALID_HANDLE;
67
68 vlsurface = CALLOC(1, sizeof(vlVdpOutputSurface));
69 if (!vlsurface)
70 return VDP_STATUS_RESOURCES;
71
72 vlsurface->device = dev;
73
74 memset(&res_tmpl, 0, sizeof(res_tmpl));
75
76 res_tmpl.target = PIPE_TEXTURE_2D;
77 res_tmpl.format = FormatRGBAToPipe(rgba_format);
78 res_tmpl.width0 = width;
79 res_tmpl.height0 = height;
80 res_tmpl.depth0 = 1;
81 res_tmpl.array_size = 1;
82 res_tmpl.bind = PIPE_BIND_SAMPLER_VIEW | PIPE_BIND_RENDER_TARGET;
83 res_tmpl.usage = PIPE_USAGE_DEFAULT;
84
85 pipe_mutex_lock(dev->mutex);
86
87 if (!CheckSurfaceParams(pipe->screen, &res_tmpl))
88 goto err_unlock;
89
90 res = pipe->screen->resource_create(pipe->screen, &res_tmpl);
91 if (!res)
92 goto err_unlock;
93
94 vlVdpDefaultSamplerViewTemplate(&sv_templ, res);
95 vlsurface->sampler_view = pipe->create_sampler_view(pipe, res, &sv_templ);
96 if (!vlsurface->sampler_view)
97 goto err_resource;
98
99 memset(&surf_templ, 0, sizeof(surf_templ));
100 surf_templ.format = res->format;
101 vlsurface->surface = pipe->create_surface(pipe, res, &surf_templ);
102 if (!vlsurface->surface)
103 goto err_resource;
104
105 *surface = vlAddDataHTAB(vlsurface);
106 if (*surface == 0)
107 goto err_resource;
108
109 pipe_resource_reference(&res, NULL);
110
111 vl_compositor_init_state(&vlsurface->cstate, pipe);
112 vl_compositor_reset_dirty_area(&vlsurface->dirty_area);
113 pipe_mutex_unlock(dev->mutex);
114
115 return VDP_STATUS_OK;
116
117 err_resource:
118 pipe_sampler_view_reference(&vlsurface->sampler_view, NULL);
119 pipe_surface_reference(&vlsurface->surface, NULL);
120 pipe_resource_reference(&res, NULL);
121 err_unlock:
122 pipe_mutex_unlock(dev->mutex);
123 FREE(vlsurface);
124 return VDP_STATUS_ERROR;
125 }
126
127 /**
128 * Destroy a VdpOutputSurface.
129 */
130 VdpStatus
131 vlVdpOutputSurfaceDestroy(VdpOutputSurface surface)
132 {
133 vlVdpOutputSurface *vlsurface;
134 struct pipe_context *pipe;
135
136 vlsurface = vlGetDataHTAB(surface);
137 if (!vlsurface)
138 return VDP_STATUS_INVALID_HANDLE;
139
140 pipe = vlsurface->device->context;
141
142 pipe_mutex_lock(vlsurface->device->mutex);
143 vlVdpResolveDelayedRendering(vlsurface->device, NULL, NULL);
144
145 pipe_surface_reference(&vlsurface->surface, NULL);
146 pipe_sampler_view_reference(&vlsurface->sampler_view, NULL);
147 pipe->screen->fence_reference(pipe->screen, &vlsurface->fence, NULL);
148 vl_compositor_cleanup_state(&vlsurface->cstate);
149 pipe_mutex_unlock(vlsurface->device->mutex);
150
151 vlRemoveDataHTAB(surface);
152 FREE(vlsurface);
153
154 return VDP_STATUS_OK;
155 }
156
157 /**
158 * Retrieve the parameters used to create a VdpOutputSurface.
159 */
160 VdpStatus
161 vlVdpOutputSurfaceGetParameters(VdpOutputSurface surface,
162 VdpRGBAFormat *rgba_format,
163 uint32_t *width, uint32_t *height)
164 {
165 vlVdpOutputSurface *vlsurface;
166
167 vlsurface = vlGetDataHTAB(surface);
168 if (!vlsurface)
169 return VDP_STATUS_INVALID_HANDLE;
170
171 *rgba_format = PipeToFormatRGBA(vlsurface->sampler_view->texture->format);
172 *width = vlsurface->sampler_view->texture->width0;
173 *height = vlsurface->sampler_view->texture->height0;
174
175 return VDP_STATUS_OK;
176 }
177
178 /**
179 * Copy image data from a VdpOutputSurface to application memory in the
180 * surface's native format.
181 */
182 VdpStatus
183 vlVdpOutputSurfaceGetBitsNative(VdpOutputSurface surface,
184 VdpRect const *source_rect,
185 void *const *destination_data,
186 uint32_t const *destination_pitches)
187 {
188 vlVdpOutputSurface *vlsurface;
189 struct pipe_context *pipe;
190 struct pipe_resource *res;
191 struct pipe_box box;
192 struct pipe_transfer *transfer;
193 uint8_t *map;
194
195 vlsurface = vlGetDataHTAB(surface);
196 if (!vlsurface)
197 return VDP_STATUS_INVALID_HANDLE;
198
199 pipe = vlsurface->device->context;
200 if (!pipe)
201 return VDP_STATUS_INVALID_HANDLE;
202
203 pipe_mutex_lock(vlsurface->device->mutex);
204 vlVdpResolveDelayedRendering(vlsurface->device, NULL, NULL);
205
206 res = vlsurface->sampler_view->texture;
207 box = RectToPipeBox(source_rect, res);
208 map = pipe->transfer_map(pipe, res, 0, PIPE_TRANSFER_READ, &box, &transfer);
209 if (!map) {
210 pipe_mutex_unlock(vlsurface->device->mutex);
211 return VDP_STATUS_RESOURCES;
212 }
213
214 util_copy_rect(*destination_data, res->format, *destination_pitches, 0, 0,
215 box.width, box.height, map, transfer->stride, 0, 0);
216
217 pipe_transfer_unmap(pipe, transfer);
218 pipe_mutex_unlock(vlsurface->device->mutex);
219
220 return VDP_STATUS_OK;
221 }
222
223 /**
224 * Copy image data from application memory in the surface's native format to
225 * a VdpOutputSurface.
226 */
227 VdpStatus
228 vlVdpOutputSurfacePutBitsNative(VdpOutputSurface surface,
229 void const *const *source_data,
230 uint32_t const *source_pitches,
231 VdpRect const *destination_rect)
232 {
233 vlVdpOutputSurface *vlsurface;
234 struct pipe_box dst_box;
235 struct pipe_context *pipe;
236
237 vlsurface = vlGetDataHTAB(surface);
238 if (!vlsurface)
239 return VDP_STATUS_INVALID_HANDLE;
240
241 pipe = vlsurface->device->context;
242 if (!pipe)
243 return VDP_STATUS_INVALID_HANDLE;
244
245 pipe_mutex_lock(vlsurface->device->mutex);
246 vlVdpResolveDelayedRendering(vlsurface->device, NULL, NULL);
247
248 dst_box = RectToPipeBox(destination_rect, vlsurface->sampler_view->texture);
249 pipe->transfer_inline_write(pipe, vlsurface->sampler_view->texture, 0,
250 PIPE_TRANSFER_WRITE, &dst_box, *source_data,
251 *source_pitches, 0);
252 pipe_mutex_unlock(vlsurface->device->mutex);
253
254 return VDP_STATUS_OK;
255 }
256
257 /**
258 * Copy image data from application memory in a specific indexed format to
259 * a VdpOutputSurface.
260 */
261 VdpStatus
262 vlVdpOutputSurfacePutBitsIndexed(VdpOutputSurface surface,
263 VdpIndexedFormat source_indexed_format,
264 void const *const *source_data,
265 uint32_t const *source_pitch,
266 VdpRect const *destination_rect,
267 VdpColorTableFormat color_table_format,
268 void const *color_table)
269 {
270 vlVdpOutputSurface *vlsurface;
271 struct pipe_context *context;
272 struct vl_compositor *compositor;
273 struct vl_compositor_state *cstate;
274
275 enum pipe_format index_format;
276 enum pipe_format colortbl_format;
277
278 struct pipe_resource *res, res_tmpl;
279 struct pipe_sampler_view sv_tmpl;
280 struct pipe_sampler_view *sv_idx = NULL, *sv_tbl = NULL;
281
282 struct pipe_box box;
283 struct u_rect dst_rect;
284
285 vlsurface = vlGetDataHTAB(surface);
286 if (!vlsurface)
287 return VDP_STATUS_INVALID_HANDLE;
288
289 context = vlsurface->device->context;
290 compositor = &vlsurface->device->compositor;
291 cstate = &vlsurface->cstate;
292
293 index_format = FormatIndexedToPipe(source_indexed_format);
294 if (index_format == PIPE_FORMAT_NONE)
295 return VDP_STATUS_INVALID_INDEXED_FORMAT;
296
297 if (!source_data || !source_pitch)
298 return VDP_STATUS_INVALID_POINTER;
299
300 colortbl_format = FormatColorTableToPipe(color_table_format);
301 if (colortbl_format == PIPE_FORMAT_NONE)
302 return VDP_STATUS_INVALID_COLOR_TABLE_FORMAT;
303
304 if (!color_table)
305 return VDP_STATUS_INVALID_POINTER;
306
307 memset(&res_tmpl, 0, sizeof(res_tmpl));
308 res_tmpl.target = PIPE_TEXTURE_2D;
309 res_tmpl.format = index_format;
310
311 if (destination_rect) {
312 res_tmpl.width0 = abs(destination_rect->x0-destination_rect->x1);
313 res_tmpl.height0 = abs(destination_rect->y0-destination_rect->y1);
314 } else {
315 res_tmpl.width0 = vlsurface->surface->texture->width0;
316 res_tmpl.height0 = vlsurface->surface->texture->height0;
317 }
318 res_tmpl.depth0 = 1;
319 res_tmpl.array_size = 1;
320 res_tmpl.usage = PIPE_USAGE_STAGING;
321 res_tmpl.bind = PIPE_BIND_SAMPLER_VIEW;
322
323 pipe_mutex_lock(vlsurface->device->mutex);
324 vlVdpResolveDelayedRendering(vlsurface->device, NULL, NULL);
325
326 if (!CheckSurfaceParams(context->screen, &res_tmpl))
327 goto error_resource;
328
329 res = context->screen->resource_create(context->screen, &res_tmpl);
330 if (!res)
331 goto error_resource;
332
333 box.x = box.y = box.z = 0;
334 box.width = res->width0;
335 box.height = res->height0;
336 box.depth = res->depth0;
337
338 context->transfer_inline_write(context, res, 0, PIPE_TRANSFER_WRITE, &box,
339 source_data[0], source_pitch[0],
340 source_pitch[0] * res->height0);
341
342 memset(&sv_tmpl, 0, sizeof(sv_tmpl));
343 u_sampler_view_default_template(&sv_tmpl, res, res->format);
344
345 sv_idx = context->create_sampler_view(context, res, &sv_tmpl);
346 pipe_resource_reference(&res, NULL);
347
348 if (!sv_idx)
349 goto error_resource;
350
351 memset(&res_tmpl, 0, sizeof(res_tmpl));
352 res_tmpl.target = PIPE_TEXTURE_1D;
353 res_tmpl.format = colortbl_format;
354 res_tmpl.width0 = 1 << util_format_get_component_bits(
355 index_format, UTIL_FORMAT_COLORSPACE_RGB, 0);
356 res_tmpl.height0 = 1;
357 res_tmpl.depth0 = 1;
358 res_tmpl.array_size = 1;
359 res_tmpl.usage = PIPE_USAGE_STAGING;
360 res_tmpl.bind = PIPE_BIND_SAMPLER_VIEW;
361
362 res = context->screen->resource_create(context->screen, &res_tmpl);
363 if (!res)
364 goto error_resource;
365
366 box.x = box.y = box.z = 0;
367 box.width = res->width0;
368 box.height = res->height0;
369 box.depth = res->depth0;
370
371 context->transfer_inline_write(context, res, 0, PIPE_TRANSFER_WRITE, &box, color_table,
372 util_format_get_stride(colortbl_format, res->width0), 0);
373
374 memset(&sv_tmpl, 0, sizeof(sv_tmpl));
375 u_sampler_view_default_template(&sv_tmpl, res, res->format);
376
377 sv_tbl = context->create_sampler_view(context, res, &sv_tmpl);
378 pipe_resource_reference(&res, NULL);
379
380 if (!sv_tbl)
381 goto error_resource;
382
383 vl_compositor_clear_layers(cstate);
384 vl_compositor_set_palette_layer(cstate, compositor, 0, sv_idx, sv_tbl, NULL, NULL, false);
385 vl_compositor_set_layer_dst_area(cstate, 0, RectToPipe(destination_rect, &dst_rect));
386 vl_compositor_render(cstate, compositor, vlsurface->surface, &vlsurface->dirty_area, false);
387
388 pipe_sampler_view_reference(&sv_idx, NULL);
389 pipe_sampler_view_reference(&sv_tbl, NULL);
390 pipe_mutex_unlock(vlsurface->device->mutex);
391
392 return VDP_STATUS_OK;
393
394 error_resource:
395 pipe_sampler_view_reference(&sv_idx, NULL);
396 pipe_sampler_view_reference(&sv_tbl, NULL);
397 pipe_mutex_unlock(vlsurface->device->mutex);
398 return VDP_STATUS_RESOURCES;
399 }
400
401 /**
402 * Copy image data from application memory in a specific YCbCr format to
403 * a VdpOutputSurface.
404 */
405 VdpStatus
406 vlVdpOutputSurfacePutBitsYCbCr(VdpOutputSurface surface,
407 VdpYCbCrFormat source_ycbcr_format,
408 void const *const *source_data,
409 uint32_t const *source_pitches,
410 VdpRect const *destination_rect,
411 VdpCSCMatrix const *csc_matrix)
412 {
413 vlVdpOutputSurface *vlsurface;
414 struct vl_compositor *compositor;
415 struct vl_compositor_state *cstate;
416
417 struct pipe_context *pipe;
418 enum pipe_format format;
419 struct pipe_video_buffer vtmpl, *vbuffer;
420 struct u_rect dst_rect;
421 struct pipe_sampler_view **sampler_views;
422
423 unsigned i;
424
425 vlsurface = vlGetDataHTAB(surface);
426 if (!vlsurface)
427 return VDP_STATUS_INVALID_HANDLE;
428
429
430 pipe = vlsurface->device->context;
431 compositor = &vlsurface->device->compositor;
432 cstate = &vlsurface->cstate;
433
434 format = FormatYCBCRToPipe(source_ycbcr_format);
435 if (format == PIPE_FORMAT_NONE)
436 return VDP_STATUS_INVALID_Y_CB_CR_FORMAT;
437
438 if (!source_data || !source_pitches)
439 return VDP_STATUS_INVALID_POINTER;
440
441 pipe_mutex_lock(vlsurface->device->mutex);
442 vlVdpResolveDelayedRendering(vlsurface->device, NULL, NULL);
443 memset(&vtmpl, 0, sizeof(vtmpl));
444 vtmpl.buffer_format = format;
445 vtmpl.chroma_format = FormatYCBCRToPipeChroma(source_ycbcr_format);
446
447 if (destination_rect) {
448 vtmpl.width = abs(destination_rect->x0-destination_rect->x1);
449 vtmpl.height = abs(destination_rect->y0-destination_rect->y1);
450 } else {
451 vtmpl.width = vlsurface->surface->texture->width0;
452 vtmpl.height = vlsurface->surface->texture->height0;
453 }
454
455 vbuffer = pipe->create_video_buffer(pipe, &vtmpl);
456 if (!vbuffer) {
457 pipe_mutex_unlock(vlsurface->device->mutex);
458 return VDP_STATUS_RESOURCES;
459 }
460
461 sampler_views = vbuffer->get_sampler_view_planes(vbuffer);
462 if (!sampler_views) {
463 vbuffer->destroy(vbuffer);
464 pipe_mutex_unlock(vlsurface->device->mutex);
465 return VDP_STATUS_RESOURCES;
466 }
467
468 for (i = 0; i < 3; ++i) {
469 struct pipe_sampler_view *sv = sampler_views[i];
470 if (!sv) continue;
471
472 struct pipe_box dst_box = {
473 0, 0, 0,
474 sv->texture->width0, sv->texture->height0, 1
475 };
476
477 pipe->transfer_inline_write(pipe, sv->texture, 0, PIPE_TRANSFER_WRITE, &dst_box,
478 source_data[i], source_pitches[i], 0);
479 }
480
481 if (!csc_matrix) {
482 vl_csc_matrix csc;
483 vl_csc_get_matrix(VL_CSC_COLOR_STANDARD_BT_601, NULL, 1, &csc);
484 vl_compositor_set_csc_matrix(cstate, (const vl_csc_matrix*)&csc);
485 } else {
486 vl_compositor_set_csc_matrix(cstate, csc_matrix);
487 }
488
489 vl_compositor_clear_layers(cstate);
490 vl_compositor_set_buffer_layer(cstate, compositor, 0, vbuffer, NULL, NULL, VL_COMPOSITOR_WEAVE);
491 vl_compositor_set_layer_dst_area(cstate, 0, RectToPipe(destination_rect, &dst_rect));
492 vl_compositor_render(cstate, compositor, vlsurface->surface, &vlsurface->dirty_area, false);
493
494 vbuffer->destroy(vbuffer);
495 pipe_mutex_unlock(vlsurface->device->mutex);
496
497 return VDP_STATUS_OK;
498 }
499
500 static unsigned
501 BlendFactorToPipe(VdpOutputSurfaceRenderBlendFactor factor)
502 {
503 switch (factor) {
504 case VDP_OUTPUT_SURFACE_RENDER_BLEND_FACTOR_ZERO:
505 return PIPE_BLENDFACTOR_ZERO;
506 case VDP_OUTPUT_SURFACE_RENDER_BLEND_FACTOR_ONE:
507 return PIPE_BLENDFACTOR_ONE;
508 case VDP_OUTPUT_SURFACE_RENDER_BLEND_FACTOR_SRC_COLOR:
509 return PIPE_BLENDFACTOR_SRC_COLOR;
510 case VDP_OUTPUT_SURFACE_RENDER_BLEND_FACTOR_ONE_MINUS_SRC_COLOR:
511 return PIPE_BLENDFACTOR_INV_SRC_COLOR;
512 case VDP_OUTPUT_SURFACE_RENDER_BLEND_FACTOR_SRC_ALPHA:
513 return PIPE_BLENDFACTOR_SRC_ALPHA;
514 case VDP_OUTPUT_SURFACE_RENDER_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA:
515 return PIPE_BLENDFACTOR_INV_SRC_ALPHA;
516 case VDP_OUTPUT_SURFACE_RENDER_BLEND_FACTOR_DST_ALPHA:
517 return PIPE_BLENDFACTOR_DST_ALPHA;
518 case VDP_OUTPUT_SURFACE_RENDER_BLEND_FACTOR_ONE_MINUS_DST_ALPHA:
519 return PIPE_BLENDFACTOR_INV_DST_ALPHA;
520 case VDP_OUTPUT_SURFACE_RENDER_BLEND_FACTOR_DST_COLOR:
521 return PIPE_BLENDFACTOR_DST_COLOR;
522 case VDP_OUTPUT_SURFACE_RENDER_BLEND_FACTOR_ONE_MINUS_DST_COLOR:
523 return PIPE_BLENDFACTOR_INV_DST_COLOR;
524 case VDP_OUTPUT_SURFACE_RENDER_BLEND_FACTOR_SRC_ALPHA_SATURATE:
525 return PIPE_BLENDFACTOR_SRC_ALPHA_SATURATE;
526 case VDP_OUTPUT_SURFACE_RENDER_BLEND_FACTOR_CONSTANT_COLOR:
527 return PIPE_BLENDFACTOR_CONST_COLOR;
528 case VDP_OUTPUT_SURFACE_RENDER_BLEND_FACTOR_ONE_MINUS_CONSTANT_COLOR:
529 return PIPE_BLENDFACTOR_INV_CONST_COLOR;
530 case VDP_OUTPUT_SURFACE_RENDER_BLEND_FACTOR_CONSTANT_ALPHA:
531 return PIPE_BLENDFACTOR_CONST_ALPHA;
532 case VDP_OUTPUT_SURFACE_RENDER_BLEND_FACTOR_ONE_MINUS_CONSTANT_ALPHA:
533 return PIPE_BLENDFACTOR_INV_CONST_ALPHA;
534 default:
535 assert(0);
536 return PIPE_BLENDFACTOR_ONE;
537 }
538 }
539
540 static unsigned
541 BlendEquationToPipe(VdpOutputSurfaceRenderBlendEquation equation)
542 {
543 switch (equation) {
544 case VDP_OUTPUT_SURFACE_RENDER_BLEND_EQUATION_SUBTRACT:
545 return PIPE_BLEND_SUBTRACT;
546 case VDP_OUTPUT_SURFACE_RENDER_BLEND_EQUATION_REVERSE_SUBTRACT:
547 return PIPE_BLEND_REVERSE_SUBTRACT;
548 case VDP_OUTPUT_SURFACE_RENDER_BLEND_EQUATION_ADD:
549 return PIPE_BLEND_ADD;
550 case VDP_OUTPUT_SURFACE_RENDER_BLEND_EQUATION_MIN:
551 return PIPE_BLEND_MIN;
552 case VDP_OUTPUT_SURFACE_RENDER_BLEND_EQUATION_MAX:
553 return PIPE_BLEND_MAX;
554 default:
555 assert(0);
556 return PIPE_BLEND_ADD;
557 }
558 }
559
560 static void *
561 BlenderToPipe(struct pipe_context *context,
562 VdpOutputSurfaceRenderBlendState const *blend_state)
563 {
564 struct pipe_blend_state blend;
565
566 memset(&blend, 0, sizeof blend);
567 blend.independent_blend_enable = 0;
568
569 if (blend_state) {
570 blend.rt[0].blend_enable = 1;
571 blend.rt[0].rgb_src_factor = BlendFactorToPipe(blend_state->blend_factor_source_color);
572 blend.rt[0].rgb_dst_factor = BlendFactorToPipe(blend_state->blend_factor_destination_color);
573 blend.rt[0].alpha_src_factor = BlendFactorToPipe(blend_state->blend_factor_source_alpha);
574 blend.rt[0].alpha_dst_factor = BlendFactorToPipe(blend_state->blend_factor_destination_alpha);
575 blend.rt[0].rgb_func = BlendEquationToPipe(blend_state->blend_equation_color);
576 blend.rt[0].alpha_func = BlendEquationToPipe(blend_state->blend_equation_alpha);
577 } else {
578 blend.rt[0].blend_enable = 0;
579 }
580
581 blend.logicop_enable = 0;
582 blend.logicop_func = PIPE_LOGICOP_CLEAR;
583 blend.rt[0].colormask = PIPE_MASK_RGBA;
584 blend.dither = 0;
585
586 return context->create_blend_state(context, &blend);
587 }
588
589 static struct vertex4f *
590 ColorsToPipe(VdpColor const *colors, uint32_t flags, struct vertex4f result[4])
591 {
592 unsigned i;
593 struct vertex4f *dst = result;
594
595 if (!colors)
596 return NULL;
597
598 for (i = 0; i < 4; ++i) {
599 dst->x = colors->red;
600 dst->y = colors->green;
601 dst->z = colors->blue;
602 dst->w = colors->alpha;
603
604 ++dst;
605 if (flags & VDP_OUTPUT_SURFACE_RENDER_COLOR_PER_VERTEX)
606 ++colors;
607 }
608 return result;
609 }
610
611 /**
612 * Composite a sub-rectangle of a VdpOutputSurface into a sub-rectangle of
613 * another VdpOutputSurface; Output Surface object VdpOutputSurface.
614 */
615 VdpStatus
616 vlVdpOutputSurfaceRenderOutputSurface(VdpOutputSurface destination_surface,
617 VdpRect const *destination_rect,
618 VdpOutputSurface source_surface,
619 VdpRect const *source_rect,
620 VdpColor const *colors,
621 VdpOutputSurfaceRenderBlendState const *blend_state,
622 uint32_t flags)
623 {
624 vlVdpOutputSurface *dst_vlsurface;
625 vlVdpOutputSurface *src_vlsurface;
626
627 struct pipe_context *context;
628 struct vl_compositor *compositor;
629 struct vl_compositor_state *cstate;
630
631 struct u_rect src_rect, dst_rect;
632
633 struct vertex4f vlcolors[4];
634 void *blend;
635
636 dst_vlsurface = vlGetDataHTAB(destination_surface);
637 if (!dst_vlsurface)
638 return VDP_STATUS_INVALID_HANDLE;
639
640 src_vlsurface = vlGetDataHTAB(source_surface);
641 if (!src_vlsurface)
642 return VDP_STATUS_INVALID_HANDLE;
643
644 if (dst_vlsurface->device != src_vlsurface->device)
645 return VDP_STATUS_HANDLE_DEVICE_MISMATCH;
646
647 pipe_mutex_lock(dst_vlsurface->device->mutex);
648 vlVdpResolveDelayedRendering(dst_vlsurface->device, NULL, NULL);
649
650 context = dst_vlsurface->device->context;
651 compositor = &dst_vlsurface->device->compositor;
652 cstate = &dst_vlsurface->cstate;
653
654 blend = BlenderToPipe(context, blend_state);
655
656 vl_compositor_clear_layers(cstate);
657 vl_compositor_set_layer_blend(cstate, 0, blend, false);
658 vl_compositor_set_rgba_layer(cstate, compositor, 0, src_vlsurface->sampler_view,
659 RectToPipe(source_rect, &src_rect), NULL,
660 ColorsToPipe(colors, flags, vlcolors));
661 STATIC_ASSERT(VL_COMPOSITOR_ROTATE_0 == VDP_OUTPUT_SURFACE_RENDER_ROTATE_0);
662 STATIC_ASSERT(VL_COMPOSITOR_ROTATE_90 == VDP_OUTPUT_SURFACE_RENDER_ROTATE_90);
663 STATIC_ASSERT(VL_COMPOSITOR_ROTATE_180 == VDP_OUTPUT_SURFACE_RENDER_ROTATE_180);
664 STATIC_ASSERT(VL_COMPOSITOR_ROTATE_270 == VDP_OUTPUT_SURFACE_RENDER_ROTATE_270);
665 vl_compositor_set_layer_rotation(cstate, 0, flags & 3);
666 vl_compositor_set_layer_dst_area(cstate, 0, RectToPipe(destination_rect, &dst_rect));
667 vl_compositor_render(cstate, compositor, dst_vlsurface->surface, &dst_vlsurface->dirty_area, false);
668
669 context->delete_blend_state(context, blend);
670 pipe_mutex_unlock(dst_vlsurface->device->mutex);
671
672 return VDP_STATUS_OK;
673 }
674
675 /**
676 * Composite a sub-rectangle of a VdpBitmapSurface into a sub-rectangle of
677 * a VdpOutputSurface; Output Surface object VdpOutputSurface.
678 */
679 VdpStatus
680 vlVdpOutputSurfaceRenderBitmapSurface(VdpOutputSurface destination_surface,
681 VdpRect const *destination_rect,
682 VdpBitmapSurface source_surface,
683 VdpRect const *source_rect,
684 VdpColor const *colors,
685 VdpOutputSurfaceRenderBlendState const *blend_state,
686 uint32_t flags)
687 {
688 vlVdpOutputSurface *dst_vlsurface;
689 vlVdpBitmapSurface *src_vlsurface;
690
691 struct pipe_context *context;
692 struct vl_compositor *compositor;
693 struct vl_compositor_state *cstate;
694
695 struct u_rect src_rect, dst_rect;
696
697 struct vertex4f vlcolors[4];
698 void *blend;
699
700 dst_vlsurface = vlGetDataHTAB(destination_surface);
701 if (!dst_vlsurface)
702 return VDP_STATUS_INVALID_HANDLE;
703
704 src_vlsurface = vlGetDataHTAB(source_surface);
705 if (!src_vlsurface)
706 return VDP_STATUS_INVALID_HANDLE;
707
708 if (dst_vlsurface->device != src_vlsurface->device)
709 return VDP_STATUS_HANDLE_DEVICE_MISMATCH;
710
711 context = dst_vlsurface->device->context;
712 compositor = &dst_vlsurface->device->compositor;
713 cstate = &dst_vlsurface->cstate;
714
715 pipe_mutex_lock(dst_vlsurface->device->mutex);
716 vlVdpResolveDelayedRendering(dst_vlsurface->device, NULL, NULL);
717
718 blend = BlenderToPipe(context, blend_state);
719
720 vl_compositor_clear_layers(cstate);
721 vl_compositor_set_layer_blend(cstate, 0, blend, false);
722 vl_compositor_set_rgba_layer(cstate, compositor, 0, src_vlsurface->sampler_view,
723 RectToPipe(source_rect, &src_rect), NULL,
724 ColorsToPipe(colors, flags, vlcolors));
725 vl_compositor_set_layer_rotation(cstate, 0, flags & 3);
726 vl_compositor_set_layer_dst_area(cstate, 0, RectToPipe(destination_rect, &dst_rect));
727 vl_compositor_render(cstate, compositor, dst_vlsurface->surface, &dst_vlsurface->dirty_area, false);
728
729 context->delete_blend_state(context, blend);
730 pipe_mutex_unlock(dst_vlsurface->device->mutex);
731
732 return VDP_STATUS_OK;
733 }
734
735 struct pipe_resource *vlVdpOutputSurfaceGallium(VdpOutputSurface surface)
736 {
737 vlVdpOutputSurface *vlsurface;
738
739 vlsurface = vlGetDataHTAB(surface);
740 if (!vlsurface || !vlsurface->surface)
741 return NULL;
742
743 pipe_mutex_lock(vlsurface->device->mutex);
744 vlVdpResolveDelayedRendering(vlsurface->device, NULL, NULL);
745 vlsurface->device->context->flush(vlsurface->device->context, NULL, 0);
746 pipe_mutex_unlock(vlsurface->device->mutex);
747
748 return vlsurface->surface->texture;
749 }