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