nvc0/ir: cache vertex out base so that we don't recompute again
[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 DeviceReference(&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_DEFAULT;
84
85 pipe_mutex_lock(dev->mutex);
86
87 if (!CheckSurfaceParams(pipe->screen, &res_tmpl))
88 goto err_unlock;
89
90 res = pipe->screen->resource_create(pipe->screen, &res_tmpl);
91 if (!res)
92 goto err_unlock;
93
94 vlVdpDefaultSamplerViewTemplate(&sv_templ, res);
95 vlsurface->sampler_view = pipe->create_sampler_view(pipe, res, &sv_templ);
96 if (!vlsurface->sampler_view)
97 goto err_resource;
98
99 memset(&surf_templ, 0, sizeof(surf_templ));
100 surf_templ.format = res->format;
101 vlsurface->surface = pipe->create_surface(pipe, res, &surf_templ);
102 if (!vlsurface->surface)
103 goto err_resource;
104
105 *surface = vlAddDataHTAB(vlsurface);
106 if (*surface == 0)
107 goto err_resource;
108
109 pipe_resource_reference(&res, NULL);
110
111 vl_compositor_init_state(&vlsurface->cstate, pipe);
112 vl_compositor_reset_dirty_area(&vlsurface->dirty_area);
113 pipe_mutex_unlock(dev->mutex);
114
115 return VDP_STATUS_OK;
116
117 err_resource:
118 pipe_sampler_view_reference(&vlsurface->sampler_view, NULL);
119 pipe_surface_reference(&vlsurface->surface, NULL);
120 pipe_resource_reference(&res, NULL);
121 err_unlock:
122 pipe_mutex_unlock(dev->mutex);
123 DeviceReference(&vlsurface->device, NULL);
124 FREE(vlsurface);
125 return VDP_STATUS_ERROR;
126 }
127
128 /**
129 * Destroy a VdpOutputSurface.
130 */
131 VdpStatus
132 vlVdpOutputSurfaceDestroy(VdpOutputSurface surface)
133 {
134 vlVdpOutputSurface *vlsurface;
135 struct pipe_context *pipe;
136
137 vlsurface = vlGetDataHTAB(surface);
138 if (!vlsurface)
139 return VDP_STATUS_INVALID_HANDLE;
140
141 pipe = vlsurface->device->context;
142
143 pipe_mutex_lock(vlsurface->device->mutex);
144 vlVdpResolveDelayedRendering(vlsurface->device, NULL, NULL);
145
146 pipe_surface_reference(&vlsurface->surface, NULL);
147 pipe_sampler_view_reference(&vlsurface->sampler_view, NULL);
148 pipe->screen->fence_reference(pipe->screen, &vlsurface->fence, NULL);
149 vl_compositor_cleanup_state(&vlsurface->cstate);
150 pipe_mutex_unlock(vlsurface->device->mutex);
151
152 vlRemoveDataHTAB(surface);
153 DeviceReference(&vlsurface->device, NULL);
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 if (!CheckSurfaceParams(context->screen, &res_tmpl))
329 goto error_resource;
330
331 res = context->screen->resource_create(context->screen, &res_tmpl);
332 if (!res)
333 goto error_resource;
334
335 box.x = box.y = box.z = 0;
336 box.width = res->width0;
337 box.height = res->height0;
338 box.depth = res->depth0;
339
340 context->transfer_inline_write(context, res, 0, PIPE_TRANSFER_WRITE, &box,
341 source_data[0], source_pitch[0],
342 source_pitch[0] * res->height0);
343
344 memset(&sv_tmpl, 0, sizeof(sv_tmpl));
345 u_sampler_view_default_template(&sv_tmpl, res, res->format);
346
347 sv_idx = context->create_sampler_view(context, res, &sv_tmpl);
348 pipe_resource_reference(&res, NULL);
349
350 if (!sv_idx)
351 goto error_resource;
352
353 memset(&res_tmpl, 0, sizeof(res_tmpl));
354 res_tmpl.target = PIPE_TEXTURE_1D;
355 res_tmpl.format = colortbl_format;
356 res_tmpl.width0 = 1 << util_format_get_component_bits(
357 index_format, UTIL_FORMAT_COLORSPACE_RGB, 0);
358 res_tmpl.height0 = 1;
359 res_tmpl.depth0 = 1;
360 res_tmpl.array_size = 1;
361 res_tmpl.usage = PIPE_USAGE_STAGING;
362 res_tmpl.bind = PIPE_BIND_SAMPLER_VIEW;
363
364 res = context->screen->resource_create(context->screen, &res_tmpl);
365 if (!res)
366 goto error_resource;
367
368 box.x = box.y = box.z = 0;
369 box.width = res->width0;
370 box.height = res->height0;
371 box.depth = res->depth0;
372
373 context->transfer_inline_write(context, res, 0, PIPE_TRANSFER_WRITE, &box, color_table,
374 util_format_get_stride(colortbl_format, res->width0), 0);
375
376 memset(&sv_tmpl, 0, sizeof(sv_tmpl));
377 u_sampler_view_default_template(&sv_tmpl, res, res->format);
378
379 sv_tbl = context->create_sampler_view(context, res, &sv_tmpl);
380 pipe_resource_reference(&res, NULL);
381
382 if (!sv_tbl)
383 goto error_resource;
384
385 vl_compositor_clear_layers(cstate);
386 vl_compositor_set_palette_layer(cstate, compositor, 0, sv_idx, sv_tbl, NULL, NULL, false);
387 vl_compositor_set_layer_dst_area(cstate, 0, RectToPipe(destination_rect, &dst_rect));
388 vl_compositor_render(cstate, compositor, vlsurface->surface, &vlsurface->dirty_area, false);
389
390 pipe_sampler_view_reference(&sv_idx, NULL);
391 pipe_sampler_view_reference(&sv_tbl, NULL);
392 pipe_mutex_unlock(vlsurface->device->mutex);
393
394 return VDP_STATUS_OK;
395
396 error_resource:
397 pipe_sampler_view_reference(&sv_idx, NULL);
398 pipe_sampler_view_reference(&sv_tbl, NULL);
399 pipe_mutex_unlock(vlsurface->device->mutex);
400 return VDP_STATUS_RESOURCES;
401 }
402
403 /**
404 * Copy image data from application memory in a specific YCbCr format to
405 * a VdpOutputSurface.
406 */
407 VdpStatus
408 vlVdpOutputSurfacePutBitsYCbCr(VdpOutputSurface surface,
409 VdpYCbCrFormat source_ycbcr_format,
410 void const *const *source_data,
411 uint32_t const *source_pitches,
412 VdpRect const *destination_rect,
413 VdpCSCMatrix const *csc_matrix)
414 {
415 vlVdpOutputSurface *vlsurface;
416 struct vl_compositor *compositor;
417 struct vl_compositor_state *cstate;
418
419 struct pipe_context *pipe;
420 enum pipe_format format;
421 struct pipe_video_buffer vtmpl, *vbuffer;
422 struct u_rect dst_rect;
423 struct pipe_sampler_view **sampler_views;
424
425 unsigned i;
426
427 vlsurface = vlGetDataHTAB(surface);
428 if (!vlsurface)
429 return VDP_STATUS_INVALID_HANDLE;
430
431
432 pipe = vlsurface->device->context;
433 compositor = &vlsurface->device->compositor;
434 cstate = &vlsurface->cstate;
435
436 format = FormatYCBCRToPipe(source_ycbcr_format);
437 if (format == PIPE_FORMAT_NONE)
438 return VDP_STATUS_INVALID_Y_CB_CR_FORMAT;
439
440 if (!source_data || !source_pitches)
441 return VDP_STATUS_INVALID_POINTER;
442
443 pipe_mutex_lock(vlsurface->device->mutex);
444 vlVdpResolveDelayedRendering(vlsurface->device, NULL, NULL);
445 memset(&vtmpl, 0, sizeof(vtmpl));
446 vtmpl.buffer_format = format;
447 vtmpl.chroma_format = FormatYCBCRToPipeChroma(source_ycbcr_format);
448
449 if (destination_rect) {
450 vtmpl.width = abs(destination_rect->x0-destination_rect->x1);
451 vtmpl.height = abs(destination_rect->y0-destination_rect->y1);
452 } else {
453 vtmpl.width = vlsurface->surface->texture->width0;
454 vtmpl.height = vlsurface->surface->texture->height0;
455 }
456
457 vbuffer = pipe->create_video_buffer(pipe, &vtmpl);
458 if (!vbuffer) {
459 pipe_mutex_unlock(vlsurface->device->mutex);
460 return VDP_STATUS_RESOURCES;
461 }
462
463 sampler_views = vbuffer->get_sampler_view_planes(vbuffer);
464 if (!sampler_views) {
465 vbuffer->destroy(vbuffer);
466 pipe_mutex_unlock(vlsurface->device->mutex);
467 return VDP_STATUS_RESOURCES;
468 }
469
470 for (i = 0; i < 3; ++i) {
471 struct pipe_sampler_view *sv = sampler_views[i];
472 if (!sv) continue;
473
474 struct pipe_box dst_box = {
475 0, 0, 0,
476 sv->texture->width0, sv->texture->height0, 1
477 };
478
479 pipe->transfer_inline_write(pipe, sv->texture, 0, PIPE_TRANSFER_WRITE, &dst_box,
480 source_data[i], source_pitches[i], 0);
481 }
482
483 if (!csc_matrix) {
484 vl_csc_matrix csc;
485 vl_csc_get_matrix(VL_CSC_COLOR_STANDARD_BT_601, NULL, 1, &csc);
486 vl_compositor_set_csc_matrix(cstate, (const vl_csc_matrix*)&csc);
487 } else {
488 vl_compositor_set_csc_matrix(cstate, csc_matrix);
489 }
490
491 vl_compositor_clear_layers(cstate);
492 vl_compositor_set_buffer_layer(cstate, compositor, 0, vbuffer, NULL, NULL, VL_COMPOSITOR_WEAVE);
493 vl_compositor_set_layer_dst_area(cstate, 0, RectToPipe(destination_rect, &dst_rect));
494 vl_compositor_render(cstate, compositor, vlsurface->surface, &vlsurface->dirty_area, false);
495
496 vbuffer->destroy(vbuffer);
497 pipe_mutex_unlock(vlsurface->device->mutex);
498
499 return VDP_STATUS_OK;
500 }
501
502 static unsigned
503 BlendFactorToPipe(VdpOutputSurfaceRenderBlendFactor factor)
504 {
505 switch (factor) {
506 case VDP_OUTPUT_SURFACE_RENDER_BLEND_FACTOR_ZERO:
507 return PIPE_BLENDFACTOR_ZERO;
508 case VDP_OUTPUT_SURFACE_RENDER_BLEND_FACTOR_ONE:
509 return PIPE_BLENDFACTOR_ONE;
510 case VDP_OUTPUT_SURFACE_RENDER_BLEND_FACTOR_SRC_COLOR:
511 return PIPE_BLENDFACTOR_SRC_COLOR;
512 case VDP_OUTPUT_SURFACE_RENDER_BLEND_FACTOR_ONE_MINUS_SRC_COLOR:
513 return PIPE_BLENDFACTOR_INV_SRC_COLOR;
514 case VDP_OUTPUT_SURFACE_RENDER_BLEND_FACTOR_SRC_ALPHA:
515 return PIPE_BLENDFACTOR_SRC_ALPHA;
516 case VDP_OUTPUT_SURFACE_RENDER_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA:
517 return PIPE_BLENDFACTOR_INV_SRC_ALPHA;
518 case VDP_OUTPUT_SURFACE_RENDER_BLEND_FACTOR_DST_ALPHA:
519 return PIPE_BLENDFACTOR_DST_ALPHA;
520 case VDP_OUTPUT_SURFACE_RENDER_BLEND_FACTOR_ONE_MINUS_DST_ALPHA:
521 return PIPE_BLENDFACTOR_INV_DST_ALPHA;
522 case VDP_OUTPUT_SURFACE_RENDER_BLEND_FACTOR_DST_COLOR:
523 return PIPE_BLENDFACTOR_DST_COLOR;
524 case VDP_OUTPUT_SURFACE_RENDER_BLEND_FACTOR_ONE_MINUS_DST_COLOR:
525 return PIPE_BLENDFACTOR_INV_DST_COLOR;
526 case VDP_OUTPUT_SURFACE_RENDER_BLEND_FACTOR_SRC_ALPHA_SATURATE:
527 return PIPE_BLENDFACTOR_SRC_ALPHA_SATURATE;
528 case VDP_OUTPUT_SURFACE_RENDER_BLEND_FACTOR_CONSTANT_COLOR:
529 return PIPE_BLENDFACTOR_CONST_COLOR;
530 case VDP_OUTPUT_SURFACE_RENDER_BLEND_FACTOR_ONE_MINUS_CONSTANT_COLOR:
531 return PIPE_BLENDFACTOR_INV_CONST_COLOR;
532 case VDP_OUTPUT_SURFACE_RENDER_BLEND_FACTOR_CONSTANT_ALPHA:
533 return PIPE_BLENDFACTOR_CONST_ALPHA;
534 case VDP_OUTPUT_SURFACE_RENDER_BLEND_FACTOR_ONE_MINUS_CONSTANT_ALPHA:
535 return PIPE_BLENDFACTOR_INV_CONST_ALPHA;
536 default:
537 assert(0);
538 return PIPE_BLENDFACTOR_ONE;
539 }
540 }
541
542 static unsigned
543 BlendEquationToPipe(VdpOutputSurfaceRenderBlendEquation equation)
544 {
545 switch (equation) {
546 case VDP_OUTPUT_SURFACE_RENDER_BLEND_EQUATION_SUBTRACT:
547 return PIPE_BLEND_SUBTRACT;
548 case VDP_OUTPUT_SURFACE_RENDER_BLEND_EQUATION_REVERSE_SUBTRACT:
549 return PIPE_BLEND_REVERSE_SUBTRACT;
550 case VDP_OUTPUT_SURFACE_RENDER_BLEND_EQUATION_ADD:
551 return PIPE_BLEND_ADD;
552 case VDP_OUTPUT_SURFACE_RENDER_BLEND_EQUATION_MIN:
553 return PIPE_BLEND_MIN;
554 case VDP_OUTPUT_SURFACE_RENDER_BLEND_EQUATION_MAX:
555 return PIPE_BLEND_MAX;
556 default:
557 assert(0);
558 return PIPE_BLEND_ADD;
559 }
560 }
561
562 static void *
563 BlenderToPipe(struct pipe_context *context,
564 VdpOutputSurfaceRenderBlendState const *blend_state)
565 {
566 struct pipe_blend_state blend;
567
568 memset(&blend, 0, sizeof blend);
569 blend.independent_blend_enable = 0;
570
571 if (blend_state) {
572 blend.rt[0].blend_enable = 1;
573 blend.rt[0].rgb_src_factor = BlendFactorToPipe(blend_state->blend_factor_source_color);
574 blend.rt[0].rgb_dst_factor = BlendFactorToPipe(blend_state->blend_factor_destination_color);
575 blend.rt[0].alpha_src_factor = BlendFactorToPipe(blend_state->blend_factor_source_alpha);
576 blend.rt[0].alpha_dst_factor = BlendFactorToPipe(blend_state->blend_factor_destination_alpha);
577 blend.rt[0].rgb_func = BlendEquationToPipe(blend_state->blend_equation_color);
578 blend.rt[0].alpha_func = BlendEquationToPipe(blend_state->blend_equation_alpha);
579 } else {
580 blend.rt[0].blend_enable = 0;
581 }
582
583 blend.logicop_enable = 0;
584 blend.logicop_func = PIPE_LOGICOP_CLEAR;
585 blend.rt[0].colormask = PIPE_MASK_RGBA;
586 blend.dither = 0;
587
588 return context->create_blend_state(context, &blend);
589 }
590
591 static struct vertex4f *
592 ColorsToPipe(VdpColor const *colors, uint32_t flags, struct vertex4f result[4])
593 {
594 unsigned i;
595 struct vertex4f *dst = result;
596
597 if (!colors)
598 return NULL;
599
600 for (i = 0; i < 4; ++i) {
601 dst->x = colors->red;
602 dst->y = colors->green;
603 dst->z = colors->blue;
604 dst->w = colors->alpha;
605
606 ++dst;
607 if (flags & VDP_OUTPUT_SURFACE_RENDER_COLOR_PER_VERTEX)
608 ++colors;
609 }
610 return result;
611 }
612
613 /**
614 * Composite a sub-rectangle of a VdpOutputSurface into a sub-rectangle of
615 * another VdpOutputSurface; Output Surface object VdpOutputSurface.
616 */
617 VdpStatus
618 vlVdpOutputSurfaceRenderOutputSurface(VdpOutputSurface destination_surface,
619 VdpRect const *destination_rect,
620 VdpOutputSurface source_surface,
621 VdpRect const *source_rect,
622 VdpColor const *colors,
623 VdpOutputSurfaceRenderBlendState const *blend_state,
624 uint32_t flags)
625 {
626 vlVdpOutputSurface *dst_vlsurface;
627
628 struct pipe_context *context;
629 struct pipe_sampler_view *src_sv;
630 struct vl_compositor *compositor;
631 struct vl_compositor_state *cstate;
632
633 struct u_rect src_rect, dst_rect;
634
635 struct vertex4f vlcolors[4];
636 void *blend;
637
638 dst_vlsurface = vlGetDataHTAB(destination_surface);
639 if (!dst_vlsurface)
640 return VDP_STATUS_INVALID_HANDLE;
641
642 if (source_surface == VDP_INVALID_HANDLE) {
643 src_sv = dst_vlsurface->device->dummy_sv;
644
645 } else {
646 vlVdpOutputSurface *src_vlsurface = vlGetDataHTAB(source_surface);
647 if (!src_vlsurface)
648 return VDP_STATUS_INVALID_HANDLE;
649
650 if (dst_vlsurface->device != src_vlsurface->device)
651 return VDP_STATUS_HANDLE_DEVICE_MISMATCH;
652
653 src_sv = src_vlsurface->sampler_view;
654 }
655
656 pipe_mutex_lock(dst_vlsurface->device->mutex);
657 vlVdpResolveDelayedRendering(dst_vlsurface->device, NULL, NULL);
658
659 context = dst_vlsurface->device->context;
660 compositor = &dst_vlsurface->device->compositor;
661 cstate = &dst_vlsurface->cstate;
662
663 blend = BlenderToPipe(context, blend_state);
664
665 vl_compositor_clear_layers(cstate);
666 vl_compositor_set_layer_blend(cstate, 0, blend, false);
667 vl_compositor_set_rgba_layer(cstate, compositor, 0, src_sv,
668 RectToPipe(source_rect, &src_rect), NULL,
669 ColorsToPipe(colors, flags, vlcolors));
670 STATIC_ASSERT(VL_COMPOSITOR_ROTATE_0 == VDP_OUTPUT_SURFACE_RENDER_ROTATE_0);
671 STATIC_ASSERT(VL_COMPOSITOR_ROTATE_90 == VDP_OUTPUT_SURFACE_RENDER_ROTATE_90);
672 STATIC_ASSERT(VL_COMPOSITOR_ROTATE_180 == VDP_OUTPUT_SURFACE_RENDER_ROTATE_180);
673 STATIC_ASSERT(VL_COMPOSITOR_ROTATE_270 == VDP_OUTPUT_SURFACE_RENDER_ROTATE_270);
674 vl_compositor_set_layer_rotation(cstate, 0, flags & 3);
675 vl_compositor_set_layer_dst_area(cstate, 0, RectToPipe(destination_rect, &dst_rect));
676 vl_compositor_render(cstate, compositor, dst_vlsurface->surface, &dst_vlsurface->dirty_area, false);
677
678 context->delete_blend_state(context, blend);
679 pipe_mutex_unlock(dst_vlsurface->device->mutex);
680
681 return VDP_STATUS_OK;
682 }
683
684 /**
685 * Composite a sub-rectangle of a VdpBitmapSurface into a sub-rectangle of
686 * a VdpOutputSurface; Output Surface object VdpOutputSurface.
687 */
688 VdpStatus
689 vlVdpOutputSurfaceRenderBitmapSurface(VdpOutputSurface destination_surface,
690 VdpRect const *destination_rect,
691 VdpBitmapSurface source_surface,
692 VdpRect const *source_rect,
693 VdpColor const *colors,
694 VdpOutputSurfaceRenderBlendState const *blend_state,
695 uint32_t flags)
696 {
697 vlVdpOutputSurface *dst_vlsurface;
698
699 struct pipe_context *context;
700 struct pipe_sampler_view *src_sv;
701 struct vl_compositor *compositor;
702 struct vl_compositor_state *cstate;
703
704 struct u_rect src_rect, dst_rect;
705
706 struct vertex4f vlcolors[4];
707 void *blend;
708
709 dst_vlsurface = vlGetDataHTAB(destination_surface);
710 if (!dst_vlsurface)
711 return VDP_STATUS_INVALID_HANDLE;
712
713 if (source_surface == VDP_INVALID_HANDLE) {
714 src_sv = dst_vlsurface->device->dummy_sv;
715
716 } else {
717 vlVdpBitmapSurface *src_vlsurface = vlGetDataHTAB(source_surface);
718 if (!src_vlsurface)
719 return VDP_STATUS_INVALID_HANDLE;
720
721 if (dst_vlsurface->device != src_vlsurface->device)
722 return VDP_STATUS_HANDLE_DEVICE_MISMATCH;
723
724 src_sv = src_vlsurface->sampler_view;
725 }
726
727 context = dst_vlsurface->device->context;
728 compositor = &dst_vlsurface->device->compositor;
729 cstate = &dst_vlsurface->cstate;
730
731 pipe_mutex_lock(dst_vlsurface->device->mutex);
732 vlVdpResolveDelayedRendering(dst_vlsurface->device, NULL, NULL);
733
734 blend = BlenderToPipe(context, blend_state);
735
736 vl_compositor_clear_layers(cstate);
737 vl_compositor_set_layer_blend(cstate, 0, blend, false);
738 vl_compositor_set_rgba_layer(cstate, compositor, 0, src_sv,
739 RectToPipe(source_rect, &src_rect), NULL,
740 ColorsToPipe(colors, flags, vlcolors));
741 vl_compositor_set_layer_rotation(cstate, 0, flags & 3);
742 vl_compositor_set_layer_dst_area(cstate, 0, RectToPipe(destination_rect, &dst_rect));
743 vl_compositor_render(cstate, compositor, dst_vlsurface->surface, &dst_vlsurface->dirty_area, false);
744
745 context->delete_blend_state(context, blend);
746 pipe_mutex_unlock(dst_vlsurface->device->mutex);
747
748 return VDP_STATUS_OK;
749 }
750
751 struct pipe_resource *vlVdpOutputSurfaceGallium(VdpOutputSurface surface)
752 {
753 vlVdpOutputSurface *vlsurface;
754
755 vlsurface = vlGetDataHTAB(surface);
756 if (!vlsurface || !vlsurface->surface)
757 return NULL;
758
759 pipe_mutex_lock(vlsurface->device->mutex);
760 vlVdpResolveDelayedRendering(vlsurface->device, NULL, NULL);
761 vlsurface->device->context->flush(vlsurface->device->context, NULL, 0);
762 pipe_mutex_unlock(vlsurface->device->mutex);
763
764 return vlsurface->surface->texture;
765 }