[g3dvl] try a different buffer aproach
[mesa.git] / src / gallium / drivers / softpipe / sp_video_context.c
1 /**************************************************************************
2 *
3 * Copyright 2009 Younes Manton.
4 * All Rights Reserved.
5 *
6 * Permission is hereby granted, free of charge, to any person obtaining a
7 * copy of this software and associated documentation files (the
8 * "Software"), to deal in the Software without restriction, including
9 * without limitation the rights to use, copy, modify, merge, publish,
10 * distribute, sub license, and/or sell copies of the Software, and to
11 * permit persons to whom the Software is furnished to do so, subject to
12 * the following conditions:
13 *
14 * The above copyright notice and this permission notice (including the
15 * next paragraph) shall be included in all copies or substantial portions
16 * of the Software.
17 *
18 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
19 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
20 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
21 * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
22 * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
23 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
24 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
25 *
26 **************************************************************************/
27
28 #include "util/u_inlines.h"
29 #include "util/u_memory.h"
30
31 #include "sp_video_context.h"
32 #include <util/u_inlines.h>
33 #include <util/u_memory.h>
34 #include <util/u_keymap.h>
35 #include <util/u_rect.h>
36 #include <util/u_video.h>
37 #include <util/u_surface.h>
38 #include "sp_public.h"
39 #include "sp_texture.h"
40
41 #define NUM_BUFFERS 8
42
43 static void
44 flush_buffer(struct sp_mpeg12_context *ctx)
45 {
46 assert(ctx);
47
48 if(ctx->mc_buffer != NULL) {
49
50 vl_mpeg12_mc_unmap_buffer(&ctx->mc_renderer, ctx->mc_buffer);
51 vl_mpeg12_mc_renderer_flush(&ctx->mc_renderer, ctx->mc_buffer);
52
53 ctx->mc_buffer = NULL;
54 }
55 }
56
57 static void
58 rotate_buffer(struct sp_mpeg12_context *ctx)
59 {
60 static unsigned key = 0;
61 struct vl_mpeg12_mc_buffer *buffer;
62
63 assert(ctx);
64
65 flush_buffer(ctx);
66
67 buffer = (struct vl_mpeg12_mc_buffer*)util_keymap_lookup(ctx->buffer_map, &key);
68 if (!buffer) {
69 boolean added_to_map;
70
71 buffer = CALLOC_STRUCT(vl_mpeg12_mc_buffer);
72 if (buffer == NULL)
73 return;
74
75 if(!vl_mpeg12_mc_init_buffer(&ctx->mc_renderer, buffer)) {
76 FREE(buffer);
77 return;
78 }
79
80 added_to_map = util_keymap_insert(ctx->buffer_map, &key, buffer, ctx);
81 assert(added_to_map);
82 }
83 ++key;
84 key %= NUM_BUFFERS;
85 ctx->mc_buffer = buffer;
86
87 vl_mpeg12_mc_map_buffer(&ctx->mc_renderer, ctx->mc_buffer);
88 }
89
90 static void
91 delete_buffer(const struct keymap *map,
92 const void *key, void *data,
93 void *user)
94 {
95 struct sp_mpeg12_context *ctx = (struct sp_mpeg12_context*)user;
96 struct vl_mpeg12_mc_buffer *buf = (struct vl_mpeg12_mc_buffer*)data;
97
98 assert(map);
99 assert(key);
100 assert(data);
101 assert(user);
102
103 vl_mpeg12_mc_cleanup_buffer(&ctx->mc_renderer, buf);
104 }
105
106 static void
107 sp_mpeg12_destroy(struct pipe_video_context *vpipe)
108 {
109 struct sp_mpeg12_context *ctx = (struct sp_mpeg12_context*)vpipe;
110
111 assert(vpipe);
112
113 flush_buffer(ctx);
114
115 /* Asserted in softpipe_delete_fs_state() for some reason */
116 ctx->pipe->bind_vs_state(ctx->pipe, NULL);
117 ctx->pipe->bind_fs_state(ctx->pipe, NULL);
118
119 ctx->pipe->delete_blend_state(ctx->pipe, ctx->blend);
120 ctx->pipe->delete_rasterizer_state(ctx->pipe, ctx->rast);
121 ctx->pipe->delete_depth_stencil_alpha_state(ctx->pipe, ctx->dsa);
122
123 pipe_surface_reference(&ctx->decode_target, NULL);
124 vl_compositor_cleanup(&ctx->compositor);
125 util_delete_keymap(ctx->buffer_map, ctx);
126 vl_mpeg12_mc_renderer_cleanup(&ctx->mc_renderer);
127 ctx->pipe->destroy(ctx->pipe);
128
129 FREE(ctx);
130 }
131
132 static int
133 sp_mpeg12_get_param(struct pipe_video_context *vpipe, int param)
134 {
135 struct sp_mpeg12_context *ctx = (struct sp_mpeg12_context*)vpipe;
136
137 assert(vpipe);
138
139 switch (param) {
140 case PIPE_CAP_NPOT_TEXTURES:
141 /* XXX: Temporary; not all paths are NPOT-tested */
142 #if 0
143 return ctx->pipe->screen->get_param(ctx->pipe->screen, param);
144 #endif
145 return FALSE;
146 case PIPE_CAP_DECODE_TARGET_PREFERRED_FORMAT:
147 return ctx->decode_format;
148 default:
149 {
150 debug_printf("Softpipe: Unknown PIPE_CAP %d\n", param);
151 return 0;
152 }
153 }
154 }
155
156 static boolean
157 sp_mpeg12_is_format_supported(struct pipe_video_context *vpipe,
158 enum pipe_format format,
159 unsigned usage,
160 unsigned geom)
161 {
162 struct sp_mpeg12_context *ctx = (struct sp_mpeg12_context*)vpipe;
163
164 assert(vpipe);
165
166 /* XXX: Temporary; not all paths are NPOT-tested */
167 if (geom & PIPE_TEXTURE_GEOM_NON_POWER_OF_TWO)
168 return FALSE;
169
170 return ctx->pipe->screen->is_format_supported(ctx->pipe->screen, format, PIPE_TEXTURE_2D,
171 0, usage, geom);
172 }
173
174 static void
175 sp_mpeg12_decode_macroblocks(struct pipe_video_context *vpipe,
176 struct pipe_surface *past,
177 struct pipe_surface *future,
178 unsigned num_macroblocks,
179 struct pipe_macroblock *macroblocks,
180 struct pipe_fence_handle **fence)
181 {
182 struct sp_mpeg12_context *ctx = (struct sp_mpeg12_context*)vpipe;
183 struct pipe_mpeg12_macroblock *mpeg12_macroblocks = (struct pipe_mpeg12_macroblock*)macroblocks;
184
185 assert(vpipe);
186 assert(num_macroblocks);
187 assert(macroblocks);
188 assert(macroblocks->codec == PIPE_VIDEO_CODEC_MPEG12);
189 assert(ctx->decode_target);
190 assert(ctx->mc_buffer);
191
192 vl_mpeg12_mc_renderer_render_macroblocks(&ctx->mc_renderer,
193 ctx->mc_buffer,
194 ctx->decode_target,
195 past, future, num_macroblocks,
196 mpeg12_macroblocks, fence);
197 }
198
199 static void
200 sp_mpeg12_surface_fill(struct pipe_video_context *vpipe,
201 struct pipe_surface *dst,
202 unsigned dstx, unsigned dsty,
203 unsigned width, unsigned height,
204 unsigned value)
205 {
206 struct sp_mpeg12_context *ctx = (struct sp_mpeg12_context*)vpipe;
207 float rgba[4] = { 0, 0, 0, 0 };
208
209 assert(vpipe);
210 assert(dst);
211
212 if (ctx->pipe->clear_render_target)
213 ctx->pipe->clear_render_target(ctx->pipe, dst, rgba, dstx, dsty, width, height);
214 else
215 util_clear_render_target(ctx->pipe, dst, rgba, dstx, dsty, width, height);
216 }
217
218 static void
219 sp_mpeg12_surface_copy(struct pipe_video_context *vpipe,
220 struct pipe_surface *dst,
221 unsigned dstx, unsigned dsty,
222 struct pipe_surface *src,
223 unsigned srcx, unsigned srcy,
224 unsigned width, unsigned height)
225 {
226 struct sp_mpeg12_context *ctx = (struct sp_mpeg12_context*)vpipe;
227
228 assert(vpipe);
229 assert(dst);
230
231 struct pipe_subresource subdst, subsrc;
232 subdst.face = dst->face;
233 subdst.level = dst->level;
234 subsrc.face = src->face;
235 subsrc.level = src->level;
236
237 if (ctx->pipe->resource_copy_region)
238 ctx->pipe->resource_copy_region(ctx->pipe, dst->texture, subdst, dstx, dsty, dst->zslice,
239 src->texture, subsrc, srcx, srcy, src->zslice,
240 width, height);
241 else
242 util_resource_copy_region(ctx->pipe, dst->texture, subdst, dstx, dsty, dst->zslice,
243 src->texture, subsrc, srcx, srcy, src->zslice,
244 width, height);
245 }
246
247 static struct pipe_transfer*
248 sp_mpeg12_get_transfer(struct pipe_video_context *vpipe,
249 struct pipe_resource *resource,
250 struct pipe_subresource subresource,
251 unsigned usage, /* a combination of PIPE_TRANSFER_x */
252 const struct pipe_box *box)
253 {
254 struct sp_mpeg12_context *ctx = (struct sp_mpeg12_context*)vpipe;
255
256 assert(vpipe);
257 assert(resource);
258 assert(box);
259
260 return ctx->pipe->get_transfer(ctx->pipe, resource, subresource, usage, box);
261 }
262
263 static void
264 sp_mpeg12_transfer_destroy(struct pipe_video_context *vpipe,
265 struct pipe_transfer *transfer)
266 {
267 struct sp_mpeg12_context *ctx = (struct sp_mpeg12_context*)vpipe;
268
269 assert(vpipe);
270 assert(transfer);
271
272 ctx->pipe->transfer_destroy(ctx->pipe, transfer);
273 }
274
275 static void*
276 sp_mpeg12_transfer_map(struct pipe_video_context *vpipe,
277 struct pipe_transfer *transfer)
278 {
279 struct sp_mpeg12_context *ctx = (struct sp_mpeg12_context*)vpipe;
280
281 assert(vpipe);
282 assert(transfer);
283
284 return ctx->pipe->transfer_map(ctx->pipe, transfer);
285 }
286
287 static void
288 sp_mpeg12_transfer_flush_region(struct pipe_video_context *vpipe,
289 struct pipe_transfer *transfer,
290 const struct pipe_box *box)
291 {
292 struct sp_mpeg12_context *ctx = (struct sp_mpeg12_context*)vpipe;
293
294 assert(vpipe);
295 assert(transfer);
296 assert(box);
297
298 ctx->pipe->transfer_flush_region(ctx->pipe, transfer, box);
299 }
300
301 static void
302 sp_mpeg12_transfer_unmap(struct pipe_video_context *vpipe,
303 struct pipe_transfer *transfer)
304 {
305 struct sp_mpeg12_context *ctx = (struct sp_mpeg12_context*)vpipe;
306
307 assert(vpipe);
308 assert(transfer);
309
310 ctx->pipe->transfer_unmap(ctx->pipe, transfer);
311 }
312
313 static void
314 sp_mpeg12_transfer_inline_write(struct pipe_video_context *vpipe,
315 struct pipe_resource *resource,
316 struct pipe_subresource subresource,
317 unsigned usage, /* a combination of PIPE_TRANSFER_x */
318 const struct pipe_box *box,
319 const void *data,
320 unsigned stride,
321 unsigned slice_stride)
322 {
323 struct sp_mpeg12_context *ctx = (struct sp_mpeg12_context*)vpipe;
324
325 assert(vpipe);
326 assert(resource);
327 assert(box);
328 assert(data);
329 assert(ctx->pipe->transfer_inline_write);
330
331 ctx->pipe->transfer_inline_write(ctx->pipe, resource, subresource, usage,
332 box, data, stride, slice_stride);
333 }
334
335 static void
336 sp_mpeg12_render_picture(struct pipe_video_context *vpipe,
337 struct pipe_surface *src_surface,
338 enum pipe_mpeg12_picture_type picture_type,
339 /*unsigned num_past_surfaces,
340 struct pipe_surface *past_surfaces,
341 unsigned num_future_surfaces,
342 struct pipe_surface *future_surfaces,*/
343 struct pipe_video_rect *src_area,
344 struct pipe_surface *dst_surface,
345 struct pipe_video_rect *dst_area,
346 struct pipe_fence_handle **fence)
347 {
348 struct sp_mpeg12_context *ctx = (struct sp_mpeg12_context*)vpipe;
349
350 assert(vpipe);
351 assert(src_surface);
352 assert(src_area);
353 assert(dst_surface);
354 assert(dst_area);
355
356 flush_buffer(ctx);
357
358 vl_compositor_render(&ctx->compositor, src_surface,
359 picture_type, src_area, dst_surface, dst_area, fence);
360 }
361
362 static void
363 sp_mpeg12_set_picture_background(struct pipe_video_context *vpipe,
364 struct pipe_surface *bg,
365 struct pipe_video_rect *bg_src_rect)
366 {
367 struct sp_mpeg12_context *ctx = (struct sp_mpeg12_context*)vpipe;
368
369 assert(vpipe);
370 assert(bg);
371 assert(bg_src_rect);
372
373 vl_compositor_set_background(&ctx->compositor, bg, bg_src_rect);
374 }
375
376 static void
377 sp_mpeg12_set_picture_layers(struct pipe_video_context *vpipe,
378 struct pipe_surface *layers[],
379 struct pipe_video_rect *src_rects[],
380 struct pipe_video_rect *dst_rects[],
381 unsigned num_layers)
382 {
383 struct sp_mpeg12_context *ctx = (struct sp_mpeg12_context*)vpipe;
384
385 assert(vpipe);
386 assert((layers && src_rects && dst_rects) ||
387 (!layers && !src_rects && !dst_rects));
388
389 vl_compositor_set_layers(&ctx->compositor, layers, src_rects, dst_rects, num_layers);
390 }
391
392 static void
393 sp_mpeg12_set_decode_target(struct pipe_video_context *vpipe,
394 struct pipe_surface *dt)
395 {
396 struct sp_mpeg12_context *ctx = (struct sp_mpeg12_context*)vpipe;
397
398 assert(vpipe);
399 assert(dt);
400
401 if (ctx->decode_target != dt || ctx->mc_buffer == NULL) {
402 rotate_buffer(ctx);
403
404 pipe_surface_reference(&ctx->decode_target, dt);
405 }
406 }
407
408 static void
409 sp_mpeg12_set_csc_matrix(struct pipe_video_context *vpipe, const float *mat)
410 {
411 struct sp_mpeg12_context *ctx = (struct sp_mpeg12_context*)vpipe;
412
413 assert(vpipe);
414
415 vl_compositor_set_csc_matrix(&ctx->compositor, mat);
416 }
417
418 static bool
419 init_pipe_state(struct sp_mpeg12_context *ctx)
420 {
421 struct pipe_rasterizer_state rast;
422 struct pipe_blend_state blend;
423 struct pipe_depth_stencil_alpha_state dsa;
424 unsigned i;
425
426 assert(ctx);
427
428 memset(&rast, 0, sizeof rast);
429 rast.flatshade = 1;
430 rast.flatshade_first = 0;
431 rast.light_twoside = 0;
432 rast.front_ccw = 1;
433 rast.cull_face = PIPE_FACE_NONE;
434 rast.fill_back = PIPE_POLYGON_MODE_FILL;
435 rast.fill_front = PIPE_POLYGON_MODE_FILL;
436 rast.offset_point = 0;
437 rast.offset_line = 0;
438 rast.scissor = 0;
439 rast.poly_smooth = 0;
440 rast.poly_stipple_enable = 0;
441 rast.sprite_coord_enable = 0;
442 rast.point_size_per_vertex = 0;
443 rast.multisample = 0;
444 rast.line_smooth = 0;
445 rast.line_stipple_enable = 0;
446 rast.line_stipple_factor = 0;
447 rast.line_stipple_pattern = 0;
448 rast.line_last_pixel = 0;
449 rast.line_width = 1;
450 rast.point_smooth = 0;
451 rast.point_quad_rasterization = 0;
452 rast.point_size = 1;
453 rast.offset_units = 1;
454 rast.offset_scale = 1;
455 rast.gl_rasterization_rules = 1;
456 ctx->rast = ctx->pipe->create_rasterizer_state(ctx->pipe, &rast);
457 ctx->pipe->bind_rasterizer_state(ctx->pipe, ctx->rast);
458
459 memset(&blend, 0, sizeof blend);
460 blend.independent_blend_enable = 0;
461 blend.rt[0].blend_enable = 0;
462 blend.rt[0].rgb_func = PIPE_BLEND_ADD;
463 blend.rt[0].rgb_src_factor = PIPE_BLENDFACTOR_ONE;
464 blend.rt[0].rgb_dst_factor = PIPE_BLENDFACTOR_ONE;
465 blend.rt[0].alpha_func = PIPE_BLEND_ADD;
466 blend.rt[0].alpha_src_factor = PIPE_BLENDFACTOR_ONE;
467 blend.rt[0].alpha_dst_factor = PIPE_BLENDFACTOR_ONE;
468 blend.logicop_enable = 0;
469 blend.logicop_func = PIPE_LOGICOP_CLEAR;
470 /* Needed to allow color writes to FB, even if blending disabled */
471 blend.rt[0].colormask = PIPE_MASK_RGBA;
472 blend.dither = 0;
473 ctx->blend = ctx->pipe->create_blend_state(ctx->pipe, &blend);
474 ctx->pipe->bind_blend_state(ctx->pipe, ctx->blend);
475
476 memset(&dsa, 0, sizeof dsa);
477 dsa.depth.enabled = 0;
478 dsa.depth.writemask = 0;
479 dsa.depth.func = PIPE_FUNC_ALWAYS;
480 for (i = 0; i < 2; ++i) {
481 dsa.stencil[i].enabled = 0;
482 dsa.stencil[i].func = PIPE_FUNC_ALWAYS;
483 dsa.stencil[i].fail_op = PIPE_STENCIL_OP_KEEP;
484 dsa.stencil[i].zpass_op = PIPE_STENCIL_OP_KEEP;
485 dsa.stencil[i].zfail_op = PIPE_STENCIL_OP_KEEP;
486 dsa.stencil[i].valuemask = 0;
487 dsa.stencil[i].writemask = 0;
488 }
489 dsa.alpha.enabled = 0;
490 dsa.alpha.func = PIPE_FUNC_ALWAYS;
491 dsa.alpha.ref_value = 0;
492 ctx->dsa = ctx->pipe->create_depth_stencil_alpha_state(ctx->pipe, &dsa);
493 ctx->pipe->bind_depth_stencil_alpha_state(ctx->pipe, ctx->dsa);
494
495 return true;
496 }
497
498 static struct pipe_video_context *
499 sp_mpeg12_create(struct pipe_context *pipe, enum pipe_video_profile profile,
500 enum pipe_video_chroma_format chroma_format,
501 unsigned width, unsigned height,
502 enum VL_MPEG12_MC_RENDERER_BUFFER_MODE bufmode,
503 bool pot_buffers,
504 enum pipe_format decode_format)
505 {
506 unsigned buffer_width, buffer_height;
507 struct sp_mpeg12_context *ctx;
508
509 assert(u_reduce_video_profile(profile) == PIPE_VIDEO_CODEC_MPEG12);
510
511 ctx = CALLOC_STRUCT(sp_mpeg12_context);
512
513 if (!ctx)
514 return NULL;
515
516 /* TODO: Non-pot buffers untested, probably doesn't work without changes to texcoord generation, vert shader, etc */
517 assert(pot_buffers);
518
519 buffer_width = pot_buffers ? util_next_power_of_two(width) : width;
520 buffer_height = pot_buffers ? util_next_power_of_two(height) : height;
521
522 ctx->base.profile = profile;
523 ctx->base.chroma_format = chroma_format;
524 ctx->base.width = width;
525 ctx->base.height = height;
526
527 ctx->base.screen = pipe->screen;
528 ctx->base.destroy = sp_mpeg12_destroy;
529 ctx->base.get_param = sp_mpeg12_get_param;
530 ctx->base.is_format_supported = sp_mpeg12_is_format_supported;
531 ctx->base.decode_macroblocks = sp_mpeg12_decode_macroblocks;
532 ctx->base.render_picture = sp_mpeg12_render_picture;
533 ctx->base.surface_fill = sp_mpeg12_surface_fill;
534 ctx->base.surface_copy = sp_mpeg12_surface_copy;
535 ctx->base.get_transfer = sp_mpeg12_get_transfer;
536 ctx->base.transfer_destroy = sp_mpeg12_transfer_destroy;
537 ctx->base.transfer_map = sp_mpeg12_transfer_map;
538 ctx->base.transfer_flush_region = sp_mpeg12_transfer_flush_region;
539 ctx->base.transfer_unmap = sp_mpeg12_transfer_unmap;
540 if (pipe->transfer_inline_write)
541 ctx->base.transfer_inline_write = sp_mpeg12_transfer_inline_write;
542 ctx->base.set_picture_background = sp_mpeg12_set_picture_background;
543 ctx->base.set_picture_layers = sp_mpeg12_set_picture_layers;
544 ctx->base.set_decode_target = sp_mpeg12_set_decode_target;
545 ctx->base.set_csc_matrix = sp_mpeg12_set_csc_matrix;
546
547 ctx->pipe = pipe;
548 ctx->decode_format = decode_format;
549
550 if (!vl_mpeg12_mc_renderer_init(&ctx->mc_renderer, ctx->pipe,
551 buffer_width, buffer_height, chroma_format,
552 bufmode)) {
553 ctx->pipe->destroy(ctx->pipe);
554 FREE(ctx);
555 return NULL;
556 }
557
558 ctx->buffer_map = util_new_keymap(sizeof(unsigned), -1, delete_buffer);
559 if (!ctx->buffer_map) {
560 vl_mpeg12_mc_renderer_cleanup(&ctx->mc_renderer);
561 ctx->pipe->destroy(ctx->pipe);
562 FREE(ctx);
563 return NULL;
564 }
565
566 if (!vl_compositor_init(&ctx->compositor, ctx->pipe)) {
567 util_delete_keymap(ctx->buffer_map, ctx);
568 vl_mpeg12_mc_renderer_cleanup(&ctx->mc_renderer);
569 ctx->pipe->destroy(ctx->pipe);
570 FREE(ctx);
571 return NULL;
572 }
573
574 if (!init_pipe_state(ctx)) {
575 vl_compositor_cleanup(&ctx->compositor);
576 util_delete_keymap(ctx->buffer_map, ctx);
577 vl_mpeg12_mc_renderer_cleanup(&ctx->mc_renderer);
578 ctx->pipe->destroy(ctx->pipe);
579 FREE(ctx);
580 return NULL;
581 }
582
583 return &ctx->base;
584 }
585
586 struct pipe_video_context *
587 sp_video_create(struct pipe_screen *screen, enum pipe_video_profile profile,
588 enum pipe_video_chroma_format chroma_format,
589 unsigned width, unsigned height, void *priv)
590 {
591 struct pipe_context *pipe;
592
593 assert(screen);
594 assert(width && height);
595
596 pipe = screen->context_create(screen, NULL);
597 if (!pipe)
598 return NULL;
599
600 /* TODO: Use slice buffering for softpipe when implemented, no advantage to buffering an entire picture with softpipe */
601 return sp_video_create_ex(pipe, profile,
602 chroma_format,
603 width, height,
604 VL_MPEG12_MC_RENDERER_BUFFER_PICTURE,
605 true,
606 PIPE_FORMAT_XYUV);
607 }
608
609 struct pipe_video_context *
610 sp_video_create_ex(struct pipe_context *pipe, enum pipe_video_profile profile,
611 enum pipe_video_chroma_format chroma_format,
612 unsigned width, unsigned height,
613 enum VL_MPEG12_MC_RENDERER_BUFFER_MODE bufmode,
614 bool pot_buffers,
615 enum pipe_format decode_format)
616 {
617 assert(pipe);
618 assert(width && height);
619
620 switch (u_reduce_video_profile(profile)) {
621 case PIPE_VIDEO_CODEC_MPEG12:
622 return sp_mpeg12_create(pipe, profile,
623 chroma_format,
624 width, height,
625 bufmode,
626 pot_buffers,
627 decode_format);
628 default:
629 return NULL;
630 }
631 }