s/Tungsten Graphics/VMware/
[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_STATIC;
84
85 pipe_mutex_lock(dev->mutex);
86 res = pipe->screen->resource_create(pipe->screen, &res_tmpl);
87 if (!res) {
88 pipe_mutex_unlock(dev->mutex);
89 FREE(dev);
90 FREE(vlsurface);
91 return VDP_STATUS_ERROR;
92 }
93
94 vlVdpDefaultSamplerViewTemplate(&sv_templ, res);
95 vlsurface->sampler_view = pipe->create_sampler_view(pipe, res, &sv_templ);
96 if (!vlsurface->sampler_view) {
97 pipe_resource_reference(&res, NULL);
98 pipe_mutex_unlock(dev->mutex);
99 FREE(dev);
100 return VDP_STATUS_ERROR;
101 }
102
103 memset(&surf_templ, 0, sizeof(surf_templ));
104 surf_templ.format = res->format;
105 vlsurface->surface = pipe->create_surface(pipe, res, &surf_templ);
106 if (!vlsurface->surface) {
107 pipe_resource_reference(&res, NULL);
108 pipe_mutex_unlock(dev->mutex);
109 FREE(dev);
110 return VDP_STATUS_ERROR;
111 }
112
113 *surface = vlAddDataHTAB(vlsurface);
114 if (*surface == 0) {
115 pipe_resource_reference(&res, NULL);
116 pipe_mutex_unlock(dev->mutex);
117 FREE(dev);
118 return VDP_STATUS_ERROR;
119 }
120
121 pipe_resource_reference(&res, NULL);
122
123 vl_compositor_init_state(&vlsurface->cstate, pipe);
124 vl_compositor_reset_dirty_area(&vlsurface->dirty_area);
125 pipe_mutex_unlock(dev->mutex);
126
127 return VDP_STATUS_OK;
128 }
129
130 /**
131 * Destroy a VdpOutputSurface.
132 */
133 VdpStatus
134 vlVdpOutputSurfaceDestroy(VdpOutputSurface surface)
135 {
136 vlVdpOutputSurface *vlsurface;
137 struct pipe_context *pipe;
138
139 vlsurface = vlGetDataHTAB(surface);
140 if (!vlsurface)
141 return VDP_STATUS_INVALID_HANDLE;
142
143 pipe = vlsurface->device->context;
144
145 pipe_mutex_lock(vlsurface->device->mutex);
146 vlVdpResolveDelayedRendering(vlsurface->device, NULL, NULL);
147
148 pipe_surface_reference(&vlsurface->surface, NULL);
149 pipe_sampler_view_reference(&vlsurface->sampler_view, NULL);
150 pipe->screen->fence_reference(pipe->screen, &vlsurface->fence, NULL);
151 vl_compositor_cleanup_state(&vlsurface->cstate);
152 pipe_mutex_unlock(vlsurface->device->mutex);
153
154 vlRemoveDataHTAB(surface);
155 FREE(vlsurface);
156
157 return VDP_STATUS_OK;
158 }
159
160 /**
161 * Retrieve the parameters used to create a VdpOutputSurface.
162 */
163 VdpStatus
164 vlVdpOutputSurfaceGetParameters(VdpOutputSurface surface,
165 VdpRGBAFormat *rgba_format,
166 uint32_t *width, uint32_t *height)
167 {
168 vlVdpOutputSurface *vlsurface;
169
170 vlsurface = vlGetDataHTAB(surface);
171 if (!vlsurface)
172 return VDP_STATUS_INVALID_HANDLE;
173
174 *rgba_format = PipeToFormatRGBA(vlsurface->sampler_view->texture->format);
175 *width = vlsurface->sampler_view->texture->width0;
176 *height = vlsurface->sampler_view->texture->height0;
177
178 return VDP_STATUS_OK;
179 }
180
181 /**
182 * Copy image data from a VdpOutputSurface to application memory in the
183 * surface's native format.
184 */
185 VdpStatus
186 vlVdpOutputSurfaceGetBitsNative(VdpOutputSurface surface,
187 VdpRect const *source_rect,
188 void *const *destination_data,
189 uint32_t const *destination_pitches)
190 {
191 vlVdpOutputSurface *vlsurface;
192 struct pipe_context *pipe;
193 struct pipe_resource *res;
194 struct pipe_box box;
195 struct pipe_transfer *transfer;
196 uint8_t *map;
197
198 vlsurface = vlGetDataHTAB(surface);
199 if (!vlsurface)
200 return VDP_STATUS_INVALID_HANDLE;
201
202 pipe = vlsurface->device->context;
203 if (!pipe)
204 return VDP_STATUS_INVALID_HANDLE;
205
206 pipe_mutex_lock(vlsurface->device->mutex);
207 vlVdpResolveDelayedRendering(vlsurface->device, NULL, NULL);
208
209 res = vlsurface->sampler_view->texture;
210 box = RectToPipeBox(source_rect, res);
211 map = pipe->transfer_map(pipe, res, 0, PIPE_TRANSFER_READ, &box, &transfer);
212 if (!map) {
213 pipe_mutex_unlock(vlsurface->device->mutex);
214 return VDP_STATUS_RESOURCES;
215 }
216
217 util_copy_rect(*destination_data, res->format, *destination_pitches, 0, 0,
218 box.width, box.height, map, transfer->stride, 0, 0);
219
220 pipe_transfer_unmap(pipe, transfer);
221 pipe_mutex_unlock(vlsurface->device->mutex);
222
223 return VDP_STATUS_OK;
224 }
225
226 /**
227 * Copy image data from application memory in the surface's native format to
228 * a VdpOutputSurface.
229 */
230 VdpStatus
231 vlVdpOutputSurfacePutBitsNative(VdpOutputSurface surface,
232 void const *const *source_data,
233 uint32_t const *source_pitches,
234 VdpRect const *destination_rect)
235 {
236 vlVdpOutputSurface *vlsurface;
237 struct pipe_box dst_box;
238 struct pipe_context *pipe;
239
240 vlsurface = vlGetDataHTAB(surface);
241 if (!vlsurface)
242 return VDP_STATUS_INVALID_HANDLE;
243
244 pipe = vlsurface->device->context;
245 if (!pipe)
246 return VDP_STATUS_INVALID_HANDLE;
247
248 pipe_mutex_lock(vlsurface->device->mutex);
249 vlVdpResolveDelayedRendering(vlsurface->device, NULL, NULL);
250
251 dst_box = RectToPipeBox(destination_rect, vlsurface->sampler_view->texture);
252 pipe->transfer_inline_write(pipe, vlsurface->sampler_view->texture, 0,
253 PIPE_TRANSFER_WRITE, &dst_box, *source_data,
254 *source_pitches, 0);
255 pipe_mutex_unlock(vlsurface->device->mutex);
256
257 return VDP_STATUS_OK;
258 }
259
260 /**
261 * Copy image data from application memory in a specific indexed format to
262 * a VdpOutputSurface.
263 */
264 VdpStatus
265 vlVdpOutputSurfacePutBitsIndexed(VdpOutputSurface surface,
266 VdpIndexedFormat source_indexed_format,
267 void const *const *source_data,
268 uint32_t const *source_pitch,
269 VdpRect const *destination_rect,
270 VdpColorTableFormat color_table_format,
271 void const *color_table)
272 {
273 vlVdpOutputSurface *vlsurface;
274 struct pipe_context *context;
275 struct vl_compositor *compositor;
276 struct vl_compositor_state *cstate;
277
278 enum pipe_format index_format;
279 enum pipe_format colortbl_format;
280
281 struct pipe_resource *res, res_tmpl;
282 struct pipe_sampler_view sv_tmpl;
283 struct pipe_sampler_view *sv_idx = NULL, *sv_tbl = NULL;
284
285 struct pipe_box box;
286 struct u_rect dst_rect;
287
288 vlsurface = vlGetDataHTAB(surface);
289 if (!vlsurface)
290 return VDP_STATUS_INVALID_HANDLE;
291
292 context = vlsurface->device->context;
293 compositor = &vlsurface->device->compositor;
294 cstate = &vlsurface->cstate;
295
296 index_format = FormatIndexedToPipe(source_indexed_format);
297 if (index_format == PIPE_FORMAT_NONE)
298 return VDP_STATUS_INVALID_INDEXED_FORMAT;
299
300 if (!source_data || !source_pitch)
301 return VDP_STATUS_INVALID_POINTER;
302
303 colortbl_format = FormatColorTableToPipe(color_table_format);
304 if (colortbl_format == PIPE_FORMAT_NONE)
305 return VDP_STATUS_INVALID_COLOR_TABLE_FORMAT;
306
307 if (!color_table)
308 return VDP_STATUS_INVALID_POINTER;
309
310 memset(&res_tmpl, 0, sizeof(res_tmpl));
311 res_tmpl.target = PIPE_TEXTURE_2D;
312 res_tmpl.format = index_format;
313
314 if (destination_rect) {
315 res_tmpl.width0 = abs(destination_rect->x0-destination_rect->x1);
316 res_tmpl.height0 = abs(destination_rect->y0-destination_rect->y1);
317 } else {
318 res_tmpl.width0 = vlsurface->surface->texture->width0;
319 res_tmpl.height0 = vlsurface->surface->texture->height0;
320 }
321 res_tmpl.depth0 = 1;
322 res_tmpl.array_size = 1;
323 res_tmpl.usage = PIPE_USAGE_STAGING;
324 res_tmpl.bind = PIPE_BIND_SAMPLER_VIEW;
325
326 pipe_mutex_lock(vlsurface->device->mutex);
327 vlVdpResolveDelayedRendering(vlsurface->device, NULL, NULL);
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 vl_compositor_set_layer_dst_area(cstate, 0, RectToPipe(destination_rect, &dst_rect));
662 vl_compositor_render(cstate, compositor, dst_vlsurface->surface, &dst_vlsurface->dirty_area, false);
663
664 context->delete_blend_state(context, blend);
665 pipe_mutex_unlock(dst_vlsurface->device->mutex);
666
667 return VDP_STATUS_OK;
668 }
669
670 /**
671 * Composite a sub-rectangle of a VdpBitmapSurface into a sub-rectangle of
672 * a VdpOutputSurface; Output Surface object VdpOutputSurface.
673 */
674 VdpStatus
675 vlVdpOutputSurfaceRenderBitmapSurface(VdpOutputSurface destination_surface,
676 VdpRect const *destination_rect,
677 VdpBitmapSurface source_surface,
678 VdpRect const *source_rect,
679 VdpColor const *colors,
680 VdpOutputSurfaceRenderBlendState const *blend_state,
681 uint32_t flags)
682 {
683 vlVdpOutputSurface *dst_vlsurface;
684 vlVdpBitmapSurface *src_vlsurface;
685
686 struct pipe_context *context;
687 struct vl_compositor *compositor;
688 struct vl_compositor_state *cstate;
689
690 struct u_rect src_rect, dst_rect;
691
692 struct vertex4f vlcolors[4];
693 void *blend;
694
695 dst_vlsurface = vlGetDataHTAB(destination_surface);
696 if (!dst_vlsurface)
697 return VDP_STATUS_INVALID_HANDLE;
698
699 src_vlsurface = vlGetDataHTAB(source_surface);
700 if (!src_vlsurface)
701 return VDP_STATUS_INVALID_HANDLE;
702
703 if (dst_vlsurface->device != src_vlsurface->device)
704 return VDP_STATUS_HANDLE_DEVICE_MISMATCH;
705
706 context = dst_vlsurface->device->context;
707 compositor = &dst_vlsurface->device->compositor;
708 cstate = &dst_vlsurface->cstate;
709
710 pipe_mutex_lock(dst_vlsurface->device->mutex);
711 vlVdpResolveDelayedRendering(dst_vlsurface->device, NULL, NULL);
712
713 blend = BlenderToPipe(context, blend_state);
714
715 vl_compositor_clear_layers(cstate);
716 vl_compositor_set_layer_blend(cstate, 0, blend, false);
717 vl_compositor_set_rgba_layer(cstate, compositor, 0, src_vlsurface->sampler_view,
718 RectToPipe(source_rect, &src_rect), NULL,
719 ColorsToPipe(colors, flags, vlcolors));
720 vl_compositor_set_layer_dst_area(cstate, 0, RectToPipe(destination_rect, &dst_rect));
721 vl_compositor_render(cstate, compositor, dst_vlsurface->surface, &dst_vlsurface->dirty_area, false);
722
723 context->delete_blend_state(context, blend);
724 pipe_mutex_unlock(dst_vlsurface->device->mutex);
725
726 return VDP_STATUS_OK;
727 }
728
729 struct pipe_resource *vlVdpOutputSurfaceGallium(VdpOutputSurface surface)
730 {
731 vlVdpOutputSurface *vlsurface;
732
733 vlsurface = vlGetDataHTAB(surface);
734 if (!vlsurface || !vlsurface->surface)
735 return NULL;
736
737 pipe_mutex_lock(vlsurface->device->mutex);
738 vlVdpResolveDelayedRendering(vlsurface->device, NULL, NULL);
739 pipe_mutex_unlock(vlsurface->device->mutex);
740
741 return vlsurface->surface->texture;
742 }