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