st/vdpau: drop unnecessary variable prof
[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 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
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 FREE(vlsurface);
90 return VDP_STATUS_ERROR;
91 }
92
93 vlVdpDefaultSamplerViewTemplate(&sv_templ, res);
94 vlsurface->sampler_view = pipe->create_sampler_view(pipe, res, &sv_templ);
95 if (!vlsurface->sampler_view) {
96 pipe_resource_reference(&res, NULL);
97 pipe_mutex_unlock(dev->mutex);
98 FREE(dev);
99 return VDP_STATUS_ERROR;
100 }
101
102 memset(&surf_templ, 0, sizeof(surf_templ));
103 surf_templ.format = res->format;
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
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
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
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 map = pipe->transfer_map(pipe, res, 0, PIPE_TRANSFER_READ, &box, &transfer);
211 if (!map) {
212 pipe_mutex_unlock(vlsurface->device->mutex);
213 return VDP_STATUS_RESOURCES;
214 }
215
216 util_copy_rect(*destination_data, res->format, *destination_pitches, 0, 0,
217 box.width, box.height, map, transfer->stride, 0, 0);
218
219 pipe_transfer_unmap(pipe, transfer);
220 pipe_mutex_unlock(vlsurface->device->mutex);
221
222 return VDP_STATUS_OK;
223 }
224
225 /**
226 * Copy image data from application memory in the surface's native format to
227 * a VdpOutputSurface.
228 */
229 VdpStatus
230 vlVdpOutputSurfacePutBitsNative(VdpOutputSurface surface,
231 void const *const *source_data,
232 uint32_t const *source_pitches,
233 VdpRect const *destination_rect)
234 {
235 vlVdpOutputSurface *vlsurface;
236 struct pipe_box dst_box;
237 struct pipe_context *pipe;
238
239 vlsurface = vlGetDataHTAB(surface);
240 if (!vlsurface)
241 return VDP_STATUS_INVALID_HANDLE;
242
243 pipe = vlsurface->device->context;
244 if (!pipe)
245 return VDP_STATUS_INVALID_HANDLE;
246
247 pipe_mutex_lock(vlsurface->device->mutex);
248 vlVdpResolveDelayedRendering(vlsurface->device, NULL, NULL);
249
250 dst_box = RectToPipeBox(destination_rect, vlsurface->sampler_view->texture);
251 pipe->transfer_inline_write(pipe, vlsurface->sampler_view->texture, 0,
252 PIPE_TRANSFER_WRITE, &dst_box, *source_data,
253 *source_pitches, 0);
254 pipe_mutex_unlock(vlsurface->device->mutex);
255
256 return VDP_STATUS_OK;
257 }
258
259 /**
260 * Copy image data from application memory in a specific indexed format to
261 * a VdpOutputSurface.
262 */
263 VdpStatus
264 vlVdpOutputSurfacePutBitsIndexed(VdpOutputSurface surface,
265 VdpIndexedFormat source_indexed_format,
266 void const *const *source_data,
267 uint32_t const *source_pitch,
268 VdpRect const *destination_rect,
269 VdpColorTableFormat color_table_format,
270 void const *color_table)
271 {
272 vlVdpOutputSurface *vlsurface;
273 struct pipe_context *context;
274 struct vl_compositor *compositor;
275 struct vl_compositor_state *cstate;
276
277 enum pipe_format index_format;
278 enum pipe_format colortbl_format;
279
280 struct pipe_resource *res, res_tmpl;
281 struct pipe_sampler_view sv_tmpl;
282 struct pipe_sampler_view *sv_idx = NULL, *sv_tbl = NULL;
283
284 struct pipe_box box;
285 struct u_rect dst_rect;
286
287 vlsurface = vlGetDataHTAB(surface);
288 if (!vlsurface)
289 return VDP_STATUS_INVALID_HANDLE;
290
291 context = vlsurface->device->context;
292 compositor = &vlsurface->device->compositor;
293 cstate = &vlsurface->cstate;
294
295 index_format = FormatIndexedToPipe(source_indexed_format);
296 if (index_format == PIPE_FORMAT_NONE)
297 return VDP_STATUS_INVALID_INDEXED_FORMAT;
298
299 if (!source_data || !source_pitch)
300 return VDP_STATUS_INVALID_POINTER;
301
302 colortbl_format = FormatColorTableToPipe(color_table_format);
303 if (colortbl_format == PIPE_FORMAT_NONE)
304 return VDP_STATUS_INVALID_COLOR_TABLE_FORMAT;
305
306 if (!color_table)
307 return VDP_STATUS_INVALID_POINTER;
308
309 memset(&res_tmpl, 0, sizeof(res_tmpl));
310 res_tmpl.target = PIPE_TEXTURE_2D;
311 res_tmpl.format = index_format;
312
313 if (destination_rect) {
314 res_tmpl.width0 = abs(destination_rect->x0-destination_rect->x1);
315 res_tmpl.height0 = abs(destination_rect->y0-destination_rect->y1);
316 } else {
317 res_tmpl.width0 = vlsurface->surface->texture->width0;
318 res_tmpl.height0 = vlsurface->surface->texture->height0;
319 }
320 res_tmpl.depth0 = 1;
321 res_tmpl.array_size = 1;
322 res_tmpl.usage = PIPE_USAGE_STAGING;
323 res_tmpl.bind = PIPE_BIND_SAMPLER_VIEW;
324
325 pipe_mutex_lock(vlsurface->device->mutex);
326 vlVdpResolveDelayedRendering(vlsurface->device, NULL, NULL);
327
328 res = context->screen->resource_create(context->screen, &res_tmpl);
329 if (!res)
330 goto error_resource;
331
332 box.x = box.y = box.z = 0;
333 box.width = res->width0;
334 box.height = res->height0;
335 box.depth = res->depth0;
336
337 context->transfer_inline_write(context, res, 0, PIPE_TRANSFER_WRITE, &box,
338 source_data[0], source_pitch[0],
339 source_pitch[0] * res->height0);
340
341 memset(&sv_tmpl, 0, sizeof(sv_tmpl));
342 u_sampler_view_default_template(&sv_tmpl, res, res->format);
343
344 sv_idx = context->create_sampler_view(context, res, &sv_tmpl);
345 pipe_resource_reference(&res, NULL);
346
347 if (!sv_idx)
348 goto error_resource;
349
350 memset(&res_tmpl, 0, sizeof(res_tmpl));
351 res_tmpl.target = PIPE_TEXTURE_1D;
352 res_tmpl.format = colortbl_format;
353 res_tmpl.width0 = 1 << util_format_get_component_bits(
354 index_format, UTIL_FORMAT_COLORSPACE_RGB, 0);
355 res_tmpl.height0 = 1;
356 res_tmpl.depth0 = 1;
357 res_tmpl.array_size = 1;
358 res_tmpl.usage = PIPE_USAGE_STAGING;
359 res_tmpl.bind = PIPE_BIND_SAMPLER_VIEW;
360
361 res = context->screen->resource_create(context->screen, &res_tmpl);
362 if (!res)
363 goto error_resource;
364
365 box.x = box.y = box.z = 0;
366 box.width = res->width0;
367 box.height = res->height0;
368 box.depth = res->depth0;
369
370 context->transfer_inline_write(context, res, 0, PIPE_TRANSFER_WRITE, &box, color_table,
371 util_format_get_stride(colortbl_format, res->width0), 0);
372
373 memset(&sv_tmpl, 0, sizeof(sv_tmpl));
374 u_sampler_view_default_template(&sv_tmpl, res, res->format);
375
376 sv_tbl = context->create_sampler_view(context, res, &sv_tmpl);
377 pipe_resource_reference(&res, NULL);
378
379 if (!sv_tbl)
380 goto error_resource;
381
382 vl_compositor_clear_layers(cstate);
383 vl_compositor_set_palette_layer(cstate, compositor, 0, sv_idx, sv_tbl, NULL, NULL, false);
384 vl_compositor_set_layer_dst_area(cstate, 0, RectToPipe(destination_rect, &dst_rect));
385 vl_compositor_render(cstate, compositor, vlsurface->surface, &vlsurface->dirty_area, false);
386
387 pipe_sampler_view_reference(&sv_idx, NULL);
388 pipe_sampler_view_reference(&sv_tbl, NULL);
389 pipe_mutex_unlock(vlsurface->device->mutex);
390
391 return VDP_STATUS_OK;
392
393 error_resource:
394 pipe_sampler_view_reference(&sv_idx, NULL);
395 pipe_sampler_view_reference(&sv_tbl, NULL);
396 pipe_mutex_unlock(vlsurface->device->mutex);
397 return VDP_STATUS_RESOURCES;
398 }
399
400 /**
401 * Copy image data from application memory in a specific YCbCr format to
402 * a VdpOutputSurface.
403 */
404 VdpStatus
405 vlVdpOutputSurfacePutBitsYCbCr(VdpOutputSurface surface,
406 VdpYCbCrFormat source_ycbcr_format,
407 void const *const *source_data,
408 uint32_t const *source_pitches,
409 VdpRect const *destination_rect,
410 VdpCSCMatrix const *csc_matrix)
411 {
412 vlVdpOutputSurface *vlsurface;
413 struct vl_compositor *compositor;
414 struct vl_compositor_state *cstate;
415
416 struct pipe_context *pipe;
417 enum pipe_format format;
418 struct pipe_video_buffer vtmpl, *vbuffer;
419 struct u_rect dst_rect;
420 struct pipe_sampler_view **sampler_views;
421
422 unsigned i;
423
424 vlsurface = vlGetDataHTAB(surface);
425 if (!vlsurface)
426 return VDP_STATUS_INVALID_HANDLE;
427
428
429 pipe = vlsurface->device->context;
430 compositor = &vlsurface->device->compositor;
431 cstate = &vlsurface->cstate;
432
433 format = FormatYCBCRToPipe(source_ycbcr_format);
434 if (format == PIPE_FORMAT_NONE)
435 return VDP_STATUS_INVALID_Y_CB_CR_FORMAT;
436
437 if (!source_data || !source_pitches)
438 return VDP_STATUS_INVALID_POINTER;
439
440 pipe_mutex_lock(vlsurface->device->mutex);
441 vlVdpResolveDelayedRendering(vlsurface->device, NULL, NULL);
442 memset(&vtmpl, 0, sizeof(vtmpl));
443 vtmpl.buffer_format = format;
444 vtmpl.chroma_format = PIPE_VIDEO_CHROMA_FORMAT_420;
445
446 if (destination_rect) {
447 vtmpl.width = abs(destination_rect->x0-destination_rect->x1);
448 vtmpl.height = abs(destination_rect->y0-destination_rect->y1);
449 } else {
450 vtmpl.width = vlsurface->surface->texture->width0;
451 vtmpl.height = vlsurface->surface->texture->height0;
452 }
453
454 vbuffer = pipe->create_video_buffer(pipe, &vtmpl);
455 if (!vbuffer) {
456 pipe_mutex_unlock(vlsurface->device->mutex);
457 return VDP_STATUS_RESOURCES;
458 }
459
460 sampler_views = vbuffer->get_sampler_view_planes(vbuffer);
461 if (!sampler_views) {
462 vbuffer->destroy(vbuffer);
463 pipe_mutex_unlock(vlsurface->device->mutex);
464 return VDP_STATUS_RESOURCES;
465 }
466
467 for (i = 0; i < 3; ++i) {
468 struct pipe_sampler_view *sv = sampler_views[i];
469 if (!sv) continue;
470
471 struct pipe_box dst_box = {
472 0, 0, 0,
473 sv->texture->width0, sv->texture->height0, 1
474 };
475
476 pipe->transfer_inline_write(pipe, sv->texture, 0, PIPE_TRANSFER_WRITE, &dst_box,
477 source_data[i], source_pitches[i], 0);
478 }
479
480 if (!csc_matrix) {
481 vl_csc_matrix csc;
482 vl_csc_get_matrix(VL_CSC_COLOR_STANDARD_BT_601, NULL, 1, &csc);
483 vl_compositor_set_csc_matrix(cstate, (const vl_csc_matrix*)&csc);
484 } else {
485 vl_compositor_set_csc_matrix(cstate, csc_matrix);
486 }
487
488 vl_compositor_clear_layers(cstate);
489 vl_compositor_set_buffer_layer(cstate, compositor, 0, vbuffer, NULL, NULL, VL_COMPOSITOR_WEAVE);
490 vl_compositor_set_layer_dst_area(cstate, 0, RectToPipe(destination_rect, &dst_rect));
491 vl_compositor_render(cstate, compositor, vlsurface->surface, &vlsurface->dirty_area, false);
492
493 vbuffer->destroy(vbuffer);
494 pipe_mutex_unlock(vlsurface->device->mutex);
495
496 return VDP_STATUS_OK;
497 }
498
499 static unsigned
500 BlendFactorToPipe(VdpOutputSurfaceRenderBlendFactor factor)
501 {
502 switch (factor) {
503 case VDP_OUTPUT_SURFACE_RENDER_BLEND_FACTOR_ZERO:
504 return PIPE_BLENDFACTOR_ZERO;
505 case VDP_OUTPUT_SURFACE_RENDER_BLEND_FACTOR_ONE:
506 return PIPE_BLENDFACTOR_ONE;
507 case VDP_OUTPUT_SURFACE_RENDER_BLEND_FACTOR_SRC_COLOR:
508 return PIPE_BLENDFACTOR_SRC_COLOR;
509 case VDP_OUTPUT_SURFACE_RENDER_BLEND_FACTOR_ONE_MINUS_SRC_COLOR:
510 return PIPE_BLENDFACTOR_INV_SRC_COLOR;
511 case VDP_OUTPUT_SURFACE_RENDER_BLEND_FACTOR_SRC_ALPHA:
512 return PIPE_BLENDFACTOR_SRC_ALPHA;
513 case VDP_OUTPUT_SURFACE_RENDER_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA:
514 return PIPE_BLENDFACTOR_INV_SRC_ALPHA;
515 case VDP_OUTPUT_SURFACE_RENDER_BLEND_FACTOR_DST_ALPHA:
516 return PIPE_BLENDFACTOR_DST_ALPHA;
517 case VDP_OUTPUT_SURFACE_RENDER_BLEND_FACTOR_ONE_MINUS_DST_ALPHA:
518 return PIPE_BLENDFACTOR_INV_DST_ALPHA;
519 case VDP_OUTPUT_SURFACE_RENDER_BLEND_FACTOR_DST_COLOR:
520 return PIPE_BLENDFACTOR_DST_COLOR;
521 case VDP_OUTPUT_SURFACE_RENDER_BLEND_FACTOR_ONE_MINUS_DST_COLOR:
522 return PIPE_BLENDFACTOR_INV_DST_COLOR;
523 case VDP_OUTPUT_SURFACE_RENDER_BLEND_FACTOR_SRC_ALPHA_SATURATE:
524 return PIPE_BLENDFACTOR_SRC_ALPHA_SATURATE;
525 case VDP_OUTPUT_SURFACE_RENDER_BLEND_FACTOR_CONSTANT_COLOR:
526 return PIPE_BLENDFACTOR_CONST_COLOR;
527 case VDP_OUTPUT_SURFACE_RENDER_BLEND_FACTOR_ONE_MINUS_CONSTANT_COLOR:
528 return PIPE_BLENDFACTOR_INV_CONST_COLOR;
529 case VDP_OUTPUT_SURFACE_RENDER_BLEND_FACTOR_CONSTANT_ALPHA:
530 return PIPE_BLENDFACTOR_CONST_ALPHA;
531 case VDP_OUTPUT_SURFACE_RENDER_BLEND_FACTOR_ONE_MINUS_CONSTANT_ALPHA:
532 return PIPE_BLENDFACTOR_INV_CONST_ALPHA;
533 default:
534 assert(0);
535 return PIPE_BLENDFACTOR_ONE;
536 }
537 }
538
539 static unsigned
540 BlendEquationToPipe(VdpOutputSurfaceRenderBlendEquation equation)
541 {
542 switch (equation) {
543 case VDP_OUTPUT_SURFACE_RENDER_BLEND_EQUATION_SUBTRACT:
544 return PIPE_BLEND_SUBTRACT;
545 case VDP_OUTPUT_SURFACE_RENDER_BLEND_EQUATION_REVERSE_SUBTRACT:
546 return PIPE_BLEND_REVERSE_SUBTRACT;
547 case VDP_OUTPUT_SURFACE_RENDER_BLEND_EQUATION_ADD:
548 return PIPE_BLEND_ADD;
549 case VDP_OUTPUT_SURFACE_RENDER_BLEND_EQUATION_MIN:
550 return PIPE_BLEND_MIN;
551 case VDP_OUTPUT_SURFACE_RENDER_BLEND_EQUATION_MAX:
552 return PIPE_BLEND_MAX;
553 default:
554 assert(0);
555 return PIPE_BLEND_ADD;
556 }
557 }
558
559 static void *
560 BlenderToPipe(struct pipe_context *context,
561 VdpOutputSurfaceRenderBlendState const *blend_state)
562 {
563 struct pipe_blend_state blend;
564
565 memset(&blend, 0, sizeof blend);
566 blend.independent_blend_enable = 0;
567
568 if (blend_state) {
569 blend.rt[0].blend_enable = 1;
570 blend.rt[0].rgb_src_factor = BlendFactorToPipe(blend_state->blend_factor_source_color);
571 blend.rt[0].rgb_dst_factor = BlendFactorToPipe(blend_state->blend_factor_destination_color);
572 blend.rt[0].alpha_src_factor = BlendFactorToPipe(blend_state->blend_factor_source_alpha);
573 blend.rt[0].alpha_dst_factor = BlendFactorToPipe(blend_state->blend_factor_destination_alpha);
574 blend.rt[0].rgb_func = BlendEquationToPipe(blend_state->blend_equation_color);
575 blend.rt[0].alpha_func = BlendEquationToPipe(blend_state->blend_equation_alpha);
576 } else {
577 blend.rt[0].blend_enable = 0;
578 }
579
580 blend.logicop_enable = 0;
581 blend.logicop_func = PIPE_LOGICOP_CLEAR;
582 blend.rt[0].colormask = PIPE_MASK_RGBA;
583 blend.dither = 0;
584
585 return context->create_blend_state(context, &blend);
586 }
587
588 static struct vertex4f *
589 ColorsToPipe(VdpColor const *colors, uint32_t flags, struct vertex4f result[4])
590 {
591 unsigned i;
592 struct vertex4f *dst = result;
593
594 if (!colors)
595 return NULL;
596
597 for (i = 0; i < 4; ++i) {
598 dst->x = colors->red;
599 dst->y = colors->green;
600 dst->z = colors->blue;
601 dst->w = colors->alpha;
602
603 ++dst;
604 if (flags & VDP_OUTPUT_SURFACE_RENDER_COLOR_PER_VERTEX)
605 ++colors;
606 }
607 return result;
608 }
609
610 /**
611 * Composite a sub-rectangle of a VdpOutputSurface into a sub-rectangle of
612 * another VdpOutputSurface; Output Surface object VdpOutputSurface.
613 */
614 VdpStatus
615 vlVdpOutputSurfaceRenderOutputSurface(VdpOutputSurface destination_surface,
616 VdpRect const *destination_rect,
617 VdpOutputSurface source_surface,
618 VdpRect const *source_rect,
619 VdpColor const *colors,
620 VdpOutputSurfaceRenderBlendState const *blend_state,
621 uint32_t flags)
622 {
623 vlVdpOutputSurface *dst_vlsurface;
624 vlVdpOutputSurface *src_vlsurface;
625
626 struct pipe_context *context;
627 struct vl_compositor *compositor;
628 struct vl_compositor_state *cstate;
629
630 struct u_rect src_rect, dst_rect;
631
632 struct vertex4f vlcolors[4];
633 void *blend;
634
635 dst_vlsurface = vlGetDataHTAB(destination_surface);
636 if (!dst_vlsurface)
637 return VDP_STATUS_INVALID_HANDLE;
638
639 src_vlsurface = vlGetDataHTAB(source_surface);
640 if (!src_vlsurface)
641 return VDP_STATUS_INVALID_HANDLE;
642
643 if (dst_vlsurface->device != src_vlsurface->device)
644 return VDP_STATUS_HANDLE_DEVICE_MISMATCH;
645
646 pipe_mutex_lock(dst_vlsurface->device->mutex);
647 vlVdpResolveDelayedRendering(dst_vlsurface->device, NULL, NULL);
648
649 context = dst_vlsurface->device->context;
650 compositor = &dst_vlsurface->device->compositor;
651 cstate = &dst_vlsurface->cstate;
652
653 blend = BlenderToPipe(context, blend_state);
654
655 vl_compositor_clear_layers(cstate);
656 vl_compositor_set_layer_blend(cstate, 0, blend, false);
657 vl_compositor_set_rgba_layer(cstate, compositor, 0, src_vlsurface->sampler_view,
658 RectToPipe(source_rect, &src_rect), NULL,
659 ColorsToPipe(colors, flags, vlcolors));
660 vl_compositor_set_layer_dst_area(cstate, 0, RectToPipe(destination_rect, &dst_rect));
661 vl_compositor_render(cstate, compositor, dst_vlsurface->surface, &dst_vlsurface->dirty_area, false);
662
663 context->delete_blend_state(context, blend);
664 pipe_mutex_unlock(dst_vlsurface->device->mutex);
665
666 return VDP_STATUS_OK;
667 }
668
669 /**
670 * Composite a sub-rectangle of a VdpBitmapSurface into a sub-rectangle of
671 * a VdpOutputSurface; Output Surface object VdpOutputSurface.
672 */
673 VdpStatus
674 vlVdpOutputSurfaceRenderBitmapSurface(VdpOutputSurface destination_surface,
675 VdpRect const *destination_rect,
676 VdpBitmapSurface source_surface,
677 VdpRect const *source_rect,
678 VdpColor const *colors,
679 VdpOutputSurfaceRenderBlendState const *blend_state,
680 uint32_t flags)
681 {
682 vlVdpOutputSurface *dst_vlsurface;
683 vlVdpBitmapSurface *src_vlsurface;
684
685 struct pipe_context *context;
686 struct vl_compositor *compositor;
687 struct vl_compositor_state *cstate;
688
689 struct u_rect src_rect, dst_rect;
690
691 struct vertex4f vlcolors[4];
692 void *blend;
693
694 dst_vlsurface = vlGetDataHTAB(destination_surface);
695 if (!dst_vlsurface)
696 return VDP_STATUS_INVALID_HANDLE;
697
698 src_vlsurface = vlGetDataHTAB(source_surface);
699 if (!src_vlsurface)
700 return VDP_STATUS_INVALID_HANDLE;
701
702 if (dst_vlsurface->device != src_vlsurface->device)
703 return VDP_STATUS_HANDLE_DEVICE_MISMATCH;
704
705 context = dst_vlsurface->device->context;
706 compositor = &dst_vlsurface->device->compositor;
707 cstate = &dst_vlsurface->cstate;
708
709 pipe_mutex_lock(dst_vlsurface->device->mutex);
710 vlVdpResolveDelayedRendering(dst_vlsurface->device, NULL, NULL);
711
712 blend = BlenderToPipe(context, blend_state);
713
714 vl_compositor_clear_layers(cstate);
715 vl_compositor_set_layer_blend(cstate, 0, blend, false);
716 vl_compositor_set_rgba_layer(cstate, compositor, 0, src_vlsurface->sampler_view,
717 RectToPipe(source_rect, &src_rect), NULL,
718 ColorsToPipe(colors, flags, vlcolors));
719 vl_compositor_set_layer_dst_area(cstate, 0, RectToPipe(destination_rect, &dst_rect));
720 vl_compositor_render(cstate, compositor, dst_vlsurface->surface, &dst_vlsurface->dirty_area, false);
721
722 context->delete_blend_state(context, blend);
723 pipe_mutex_unlock(dst_vlsurface->device->mutex);
724
725 return VDP_STATUS_OK;
726 }