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