nvc0: fix up video buffer alignment requirements
[mesa.git] / src / gallium / drivers / nvc0 / nvc0_video.c
1 /*
2 * Copyright 2011-2013 Maarten Lankhorst
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 * and/or sell copies of the Software, and to permit persons to whom the
9 * Software is furnished to do so, subject to the following conditions:
10 *
11 * The above copyright notice and this permission notice shall be included in
12 * all copies or substantial portions of the Software.
13 *
14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
17 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
18 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
19 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
20 * OTHER DEALINGS IN THE SOFTWARE.
21 */
22
23 #include "nvc0_video.h"
24
25 #include "util/u_sampler.h"
26 #include "util/u_format.h"
27
28 #include <sys/mman.h>
29 #include <fcntl.h>
30
31 int
32 nvc0_screen_get_video_param(struct pipe_screen *pscreen,
33 enum pipe_video_profile profile,
34 enum pipe_video_cap param)
35 {
36 switch (param) {
37 case PIPE_VIDEO_CAP_SUPPORTED:
38 return profile >= PIPE_VIDEO_PROFILE_MPEG1;
39 case PIPE_VIDEO_CAP_NPOT_TEXTURES:
40 return 1;
41 case PIPE_VIDEO_CAP_MAX_WIDTH:
42 case PIPE_VIDEO_CAP_MAX_HEIGHT:
43 return nouveau_screen(pscreen)->device->chipset < 0xd0 ? 2048 : 4096;
44 case PIPE_VIDEO_CAP_PREFERED_FORMAT:
45 return PIPE_FORMAT_NV12;
46 case PIPE_VIDEO_CAP_SUPPORTS_INTERLACED:
47 case PIPE_VIDEO_CAP_PREFERS_INTERLACED:
48 return true;
49 case PIPE_VIDEO_CAP_SUPPORTS_PROGRESSIVE:
50 return false;
51 default:
52 debug_printf("unknown video param: %d\n", param);
53 return 0;
54 }
55 }
56
57 static void
58 nvc0_decoder_decode_bitstream(struct pipe_video_decoder *decoder,
59 struct pipe_video_buffer *video_target,
60 struct pipe_picture_desc *picture,
61 unsigned num_buffers,
62 const void *const *data,
63 const unsigned *num_bytes)
64 {
65 struct nvc0_decoder *dec = (struct nvc0_decoder *)decoder;
66 struct nvc0_video_buffer *target = (struct nvc0_video_buffer *)video_target;
67 uint32_t comm_seq = ++dec->fence_seq;
68 union pipe_desc desc;
69
70 unsigned vp_caps, is_ref, ret;
71 struct nvc0_video_buffer *refs[16] = {};
72
73 desc.base = picture;
74
75 assert(target->base.buffer_format == PIPE_FORMAT_NV12);
76
77 ret = nvc0_decoder_bsp(dec, desc, target, comm_seq,
78 num_buffers, data, num_bytes,
79 &vp_caps, &is_ref, refs);
80
81 /* did we decode bitstream correctly? */
82 assert(ret == 2);
83
84 nvc0_decoder_vp(dec, desc, target, comm_seq, vp_caps, is_ref, refs);
85 nvc0_decoder_ppp(dec, desc, target, comm_seq);
86 }
87
88 static void
89 nvc0_decoder_flush(struct pipe_video_decoder *decoder)
90 {
91 struct nvc0_decoder *dec = (struct nvc0_decoder *)decoder;
92 (void)dec;
93 }
94
95 static void
96 nvc0_decoder_begin_frame(struct pipe_video_decoder *decoder,
97 struct pipe_video_buffer *target,
98 struct pipe_picture_desc *picture)
99 {
100 }
101
102 static void
103 nvc0_decoder_end_frame(struct pipe_video_decoder *decoder,
104 struct pipe_video_buffer *target,
105 struct pipe_picture_desc *picture)
106 {
107 }
108
109 static void
110 nvc0_decoder_destroy(struct pipe_video_decoder *decoder)
111 {
112 struct nvc0_decoder *dec = (struct nvc0_decoder *)decoder;
113 int i;
114
115 nouveau_bo_ref(NULL, &dec->ref_bo);
116 nouveau_bo_ref(NULL, &dec->bitplane_bo);
117 nouveau_bo_ref(NULL, &dec->inter_bo[0]);
118 nouveau_bo_ref(NULL, &dec->inter_bo[1]);
119 #ifdef NVC0_DEBUG_FENCE
120 nouveau_bo_ref(NULL, &dec->fence_bo);
121 #endif
122 nouveau_bo_ref(NULL, &dec->fw_bo);
123
124 for (i = 0; i < NVC0_VIDEO_QDEPTH; ++i)
125 nouveau_bo_ref(NULL, &dec->bsp_bo[i]);
126
127 nouveau_object_del(&dec->bsp);
128 nouveau_object_del(&dec->vp);
129 nouveau_object_del(&dec->ppp);
130
131 if (dec->channel[0] != dec->channel[1]) {
132 for (i = 0; i < 3; ++i) {
133 nouveau_pushbuf_del(&dec->pushbuf[i]);
134 nouveau_object_del(&dec->channel[i]);
135 }
136 } else {
137 nouveau_pushbuf_del(dec->pushbuf);
138 nouveau_object_del(dec->channel);
139 }
140
141 FREE(dec);
142 }
143
144 static void nvc0_video_getpath(enum pipe_video_profile profile, char *path)
145 {
146 switch (u_reduce_video_profile(profile)) {
147 case PIPE_VIDEO_CODEC_MPEG12: {
148 sprintf(path, "/lib/firmware/nouveau/vuc-mpeg12-0");
149 break;
150 }
151 case PIPE_VIDEO_CODEC_MPEG4: {
152 sprintf(path, "/lib/firmware/nouveau/vuc-mpeg4-0");
153 break;
154 }
155 case PIPE_VIDEO_CODEC_VC1: {
156 sprintf(path, "/lib/firmware/nouveau/vuc-vc1-%u", profile - PIPE_VIDEO_PROFILE_VC1_SIMPLE);
157 break;
158 }
159 case PIPE_VIDEO_CODEC_MPEG4_AVC: {
160 sprintf(path, "/lib/firmware/nouveau/vuc-h264-0");
161 break;
162 }
163 default: assert(0);
164 }
165 }
166
167 struct pipe_video_decoder *
168 nvc0_create_decoder(struct pipe_context *context,
169 enum pipe_video_profile profile,
170 enum pipe_video_entrypoint entrypoint,
171 enum pipe_video_chroma_format chroma_format,
172 unsigned width, unsigned height, unsigned max_references,
173 bool chunked_decode)
174 {
175 struct nouveau_screen *screen = &((struct nvc0_context *)context)->screen->base;
176 struct nvc0_decoder *dec;
177 struct nouveau_pushbuf **push;
178 union nouveau_bo_config cfg;
179 bool kepler = screen->device->chipset >= 0xe0;
180
181 cfg.nvc0.tile_mode = 0x10;
182 cfg.nvc0.memtype = 0xfe;
183
184 int ret, i;
185 uint32_t codec = 1, ppp_codec = 3;
186 uint32_t timeout;
187 u32 tmp_size = 0;
188
189 if (getenv("XVMC_VL"))
190 return vl_create_decoder(context, profile, entrypoint,
191 chroma_format, width, height,
192 max_references, chunked_decode);
193
194 if (entrypoint != PIPE_VIDEO_ENTRYPOINT_BITSTREAM) {
195 debug_printf("%x\n", entrypoint);
196 return NULL;
197 }
198
199 dec = CALLOC_STRUCT(nvc0_decoder);
200 if (!dec)
201 return NULL;
202 dec->client = screen->client;
203
204 if (!kepler) {
205 dec->bsp_idx = 5;
206 dec->vp_idx = 6;
207 dec->ppp_idx = 7;
208 } else {
209 dec->bsp_idx = 2;
210 dec->vp_idx = 2;
211 dec->ppp_idx = 2;
212 }
213
214 for (i = 0; i < 3; ++i)
215 if (i && !kepler) {
216 dec->channel[i] = dec->channel[0];
217 dec->pushbuf[i] = dec->pushbuf[0];
218 } else {
219 void *data;
220 u32 size;
221 struct nvc0_fifo nvc0_args = {};
222 struct nve0_fifo nve0_args = {};
223
224 if (!kepler) {
225 size = sizeof(nvc0_args);
226 data = &nvc0_args;
227 } else {
228 unsigned engine[] = {
229 NVE0_FIFO_ENGINE_BSP,
230 NVE0_FIFO_ENGINE_VP,
231 NVE0_FIFO_ENGINE_PPP
232 };
233
234 nve0_args.engine = engine[i];
235 size = sizeof(nve0_args);
236 data = &nve0_args;
237 }
238
239 ret = nouveau_object_new(&screen->device->object, 0,
240 NOUVEAU_FIFO_CHANNEL_CLASS,
241 data, size, &dec->channel[i]);
242
243 if (!ret)
244 ret = nouveau_pushbuf_new(screen->client, dec->channel[i], 4,
245 32 * 1024, true, &dec->pushbuf[i]);
246 if (ret)
247 break;
248 }
249 push = dec->pushbuf;
250
251 if (!kepler) {
252 if (!ret)
253 ret = nouveau_object_new(dec->channel[0], 0x390b1, 0x90b1, NULL, 0, &dec->bsp);
254 if (!ret)
255 ret = nouveau_object_new(dec->channel[1], 0x190b2, 0x90b2, NULL, 0, &dec->vp);
256 if (!ret)
257 ret = nouveau_object_new(dec->channel[2], 0x290b3, 0x90b3, NULL, 0, &dec->ppp);
258 } else {
259 if (!ret)
260 ret = nouveau_object_new(dec->channel[0], 0x95b1, 0x95b1, NULL, 0, &dec->bsp);
261 if (!ret)
262 ret = nouveau_object_new(dec->channel[1], 0x95b2, 0x95b2, NULL, 0, &dec->vp);
263 if (!ret)
264 ret = nouveau_object_new(dec->channel[2], 0x90b3, 0x90b3, NULL, 0, &dec->ppp);
265 }
266 if (ret)
267 goto fail;
268
269 BEGIN_NVC0(push[0], SUBC_BSP(NV01_SUBCHAN_OBJECT), 1);
270 PUSH_DATA (push[0], dec->bsp->handle);
271
272 BEGIN_NVC0(push[1], SUBC_VP(NV01_SUBCHAN_OBJECT), 1);
273 PUSH_DATA (push[1], dec->vp->handle);
274
275 BEGIN_NVC0(push[2], SUBC_PPP(NV01_SUBCHAN_OBJECT), 1);
276 PUSH_DATA (push[2], dec->ppp->handle);
277
278 dec->base.context = context;
279 dec->base.profile = profile;
280 dec->base.entrypoint = entrypoint;
281 dec->base.chroma_format = chroma_format;
282 dec->base.width = width;
283 dec->base.height = height;
284 dec->base.max_references = max_references;
285 dec->base.destroy = nvc0_decoder_destroy;
286 dec->base.flush = nvc0_decoder_flush;
287 dec->base.decode_bitstream = nvc0_decoder_decode_bitstream;
288 dec->base.begin_frame = nvc0_decoder_begin_frame;
289 dec->base.end_frame = nvc0_decoder_end_frame;
290
291 for (i = 0; i < NVC0_VIDEO_QDEPTH && !ret; ++i)
292 ret = nouveau_bo_new(screen->device, NOUVEAU_BO_VRAM,
293 0, 1 << 20, &cfg, &dec->bsp_bo[i]);
294 if (!ret)
295 ret = nouveau_bo_new(screen->device, NOUVEAU_BO_VRAM,
296 0x100, 4 << 20, &cfg, &dec->inter_bo[0]);
297 if (!ret) {
298 if (!kepler)
299 nouveau_bo_ref(dec->inter_bo[0], &dec->inter_bo[1]);
300 else
301 ret = nouveau_bo_new(screen->device, NOUVEAU_BO_VRAM,
302 0x100, dec->inter_bo[0]->size, &cfg,
303 &dec->inter_bo[1]);
304 }
305 if (ret)
306 goto fail;
307
308 switch (u_reduce_video_profile(profile)) {
309 case PIPE_VIDEO_CODEC_MPEG12: {
310 codec = 1;
311 assert(max_references <= 2);
312 break;
313 }
314 case PIPE_VIDEO_CODEC_MPEG4: {
315 codec = 4;
316 tmp_size = mb(height)*16 * mb(width)*16;
317 assert(max_references <= 2);
318 break;
319 }
320 case PIPE_VIDEO_CODEC_VC1: {
321 ppp_codec = codec = 2;
322 tmp_size = mb(height)*16 * mb(width)*16;
323 assert(max_references <= 2);
324 break;
325 }
326 case PIPE_VIDEO_CODEC_MPEG4_AVC: {
327 codec = 3;
328 dec->tmp_stride = 16 * mb_half(width) * nvc0_video_align(height) * 3 / 2;
329 tmp_size = dec->tmp_stride * (max_references + 1);
330 assert(max_references <= 16);
331 break;
332 }
333 default:
334 fprintf(stderr, "invalid codec\n");
335 goto fail;
336 }
337
338 if (screen->device->chipset < 0xd0) {
339 int fd;
340 char path[PATH_MAX];
341 ssize_t r;
342 uint32_t *end, endval;
343
344 ret = nouveau_bo_new(screen->device, NOUVEAU_BO_VRAM, 0,
345 0x4000, &cfg, &dec->fw_bo);
346 if (!ret)
347 ret = nouveau_bo_map(dec->fw_bo, NOUVEAU_BO_WR, dec->client);
348 if (ret)
349 goto fail;
350
351 nvc0_video_getpath(profile, path);
352
353 fd = open(path, O_RDONLY | O_CLOEXEC);
354 if (fd < 0) {
355 fprintf(stderr, "opening firmware file %s failed: %m\n", path);
356 goto fw_fail;
357 }
358 r = read(fd, dec->fw_bo->map, 0x4000);
359 close(fd);
360
361 if (r < 0) {
362 fprintf(stderr, "reading firmware file %s failed: %m\n", path);
363 goto fw_fail;
364 }
365
366 if (r == 0x4000) {
367 fprintf(stderr, "firmware file %s too large!\n", path);
368 goto fw_fail;
369 }
370
371 if (r & 0xff) {
372 fprintf(stderr, "firmware file %s wrong size!\n", path);
373 goto fw_fail;
374 }
375
376 end = dec->fw_bo->map + r - 4;
377 endval = *end;
378 while (endval == *end)
379 end--;
380
381 r = (intptr_t)end - (intptr_t)dec->fw_bo->map + 4;
382
383 switch (u_reduce_video_profile(profile)) {
384 case PIPE_VIDEO_CODEC_MPEG12: {
385 assert((r & 0xff) == 0xe0);
386 dec->fw_sizes = (0x2e0<<16) | (r - 0x2e0);
387 break;
388 }
389 case PIPE_VIDEO_CODEC_MPEG4: {
390 assert((r & 0xff) == 0xe0);
391 dec->fw_sizes = (0x2e0<<16) | (r - 0x2e0);
392 break;
393 }
394 case PIPE_VIDEO_CODEC_VC1: {
395 assert((r & 0xff) == 0xac);
396 dec->fw_sizes = (0x3ac<<16) | (r - 0x3ac);
397 break;
398 }
399 case PIPE_VIDEO_CODEC_MPEG4_AVC: {
400 assert((r & 0xff) == 0x70);
401 dec->fw_sizes = (0x370<<16) | (r - 0x370);
402 break;
403 }
404 default:
405 goto fw_fail;
406 }
407 munmap(dec->fw_bo->map, dec->fw_bo->size);
408 dec->fw_bo->map = NULL;
409 }
410
411 if (codec != 3) {
412 ret = nouveau_bo_new(screen->device, NOUVEAU_BO_VRAM, 0,
413 0x400, &cfg, &dec->bitplane_bo);
414 if (ret)
415 goto fail;
416 }
417
418 dec->ref_stride = mb(width)*16 * (mb_half(height)*32 + nvc0_video_align(height)/2);
419 ret = nouveau_bo_new(screen->device, NOUVEAU_BO_VRAM, 0,
420 dec->ref_stride * (max_references+2) + tmp_size,
421 &cfg, &dec->ref_bo);
422 if (ret)
423 goto fail;
424
425 timeout = 0;
426
427 BEGIN_NVC0(push[0], SUBC_BSP(0x200), 2);
428 PUSH_DATA (push[0], codec);
429 PUSH_DATA (push[0], timeout);
430
431 BEGIN_NVC0(push[1], SUBC_VP(0x200), 2);
432 PUSH_DATA (push[1], codec);
433 PUSH_DATA (push[1], timeout);
434
435 BEGIN_NVC0(push[2], SUBC_PPP(0x200), 2);
436 PUSH_DATA (push[2], ppp_codec);
437 PUSH_DATA (push[2], timeout);
438
439 ++dec->fence_seq;
440
441 #if NVC0_DEBUG_FENCE
442 ret = nouveau_bo_new(screen->device, NOUVEAU_BO_GART|NOUVEAU_BO_MAP,
443 0, 0x1000, &cfg, &dec->fence_bo);
444 if (ret)
445 goto fail;
446
447 nouveau_bo_map(dec->fence_bo, NOUVEAU_BO_RDWR, screen->client);
448 dec->fence_map = dec->fence_bo->map;
449 dec->fence_map[0] = dec->fence_map[4] = dec->fence_map[8] = 0;
450 dec->comm = (struct comm *)(dec->fence_map + (COMM_OFFSET/sizeof(*dec->fence_map)));
451
452 /* So lets test if the fence is working? */
453 BEGIN_NVC0(push[0], SUBC_BSP(0x240), 3);
454 PUSH_DATAh(push[0], dec->fence_bo->offset);
455 PUSH_DATA (push[0], dec->fence_bo->offset);
456 PUSH_DATA (push[0], dec->fence_seq);
457
458 BEGIN_NVC0(push[0], SUBC_BSP(0x304), 1);
459 PUSH_DATA (push[0], 1);
460 PUSH_KICK (push[0]);
461
462 BEGIN_NVC0(push[1], SUBC_VP(0x240), 3);
463 PUSH_DATAh(push[1], (dec->fence_bo->offset + 0x10));
464 PUSH_DATA (push[1], (dec->fence_bo->offset + 0x10));
465 PUSH_DATA (push[1], dec->fence_seq);
466
467 BEGIN_NVC0(push[1], SUBC_VP(0x304), 1);
468 PUSH_DATA (push[1], 1);
469 PUSH_KICK (push[1]);
470
471 BEGIN_NVC0(push[2], SUBC_PPP(0x240), 3);
472 PUSH_DATAh(push[2], (dec->fence_bo->offset + 0x20));
473 PUSH_DATA (push[2], (dec->fence_bo->offset + 0x20));
474 PUSH_DATA (push[2], dec->fence_seq);
475
476 BEGIN_NVC0(push[2], SUBC_PPP(0x304), 1);
477 PUSH_DATA (push[2], 1);
478 PUSH_KICK (push[2]);
479
480 usleep(100);
481 while (dec->fence_seq > dec->fence_map[0] &&
482 dec->fence_seq > dec->fence_map[4] &&
483 dec->fence_seq > dec->fence_map[8]) {
484 debug_printf("%u: %u %u %u\n", dec->fence_seq, dec->fence_map[0], dec->fence_map[4], dec->fence_map[8]);
485 usleep(100);
486 }
487 debug_printf("%u: %u %u %u\n", dec->fence_seq, dec->fence_map[0], dec->fence_map[4], dec->fence_map[8]);
488 #endif
489
490 return &dec->base;
491
492 fw_fail:
493 debug_printf("Cannot create decoder without firmware..\n");
494 nvc0_decoder_destroy(&dec->base);
495 return NULL;
496
497 fail:
498 debug_printf("Creation failed: %s (%i)\n", strerror(-ret), ret);
499 nvc0_decoder_destroy(&dec->base);
500 return NULL;
501 }
502
503 static struct pipe_sampler_view **
504 nvc0_video_buffer_sampler_view_planes(struct pipe_video_buffer *buffer)
505 {
506 struct nvc0_video_buffer *buf = (struct nvc0_video_buffer *)buffer;
507 return buf->sampler_view_planes;
508 }
509
510 static struct pipe_sampler_view **
511 nvc0_video_buffer_sampler_view_components(struct pipe_video_buffer *buffer)
512 {
513 struct nvc0_video_buffer *buf = (struct nvc0_video_buffer *)buffer;
514 return buf->sampler_view_components;
515 }
516
517 static struct pipe_surface **
518 nvc0_video_buffer_surfaces(struct pipe_video_buffer *buffer)
519 {
520 struct nvc0_video_buffer *buf = (struct nvc0_video_buffer *)buffer;
521 return buf->surfaces;
522 }
523
524 static void
525 nvc0_video_buffer_destroy(struct pipe_video_buffer *buffer)
526 {
527 struct nvc0_video_buffer *buf = (struct nvc0_video_buffer *)buffer;
528 unsigned i;
529
530 assert(buf);
531
532 for (i = 0; i < VL_NUM_COMPONENTS; ++i) {
533 pipe_resource_reference(&buf->resources[i], NULL);
534 pipe_sampler_view_reference(&buf->sampler_view_planes[i], NULL);
535 pipe_sampler_view_reference(&buf->sampler_view_components[i], NULL);
536 pipe_surface_reference(&buf->surfaces[i * 2], NULL);
537 pipe_surface_reference(&buf->surfaces[i * 2 + 1], NULL);
538 }
539 FREE(buffer);
540 }
541
542 struct pipe_video_buffer *
543 nvc0_video_buffer_create(struct pipe_context *pipe,
544 const struct pipe_video_buffer *templat)
545 {
546 struct nvc0_video_buffer *buffer;
547 struct pipe_resource templ;
548 unsigned i, j, component;
549 struct pipe_sampler_view sv_templ;
550 struct pipe_surface surf_templ;
551
552 assert(templat->interlaced);
553 if (getenv("XVMC_VL") || templat->buffer_format != PIPE_FORMAT_NV12)
554 return vl_video_buffer_create(pipe, templat);
555
556 assert(templat->chroma_format == PIPE_VIDEO_CHROMA_FORMAT_420);
557
558 buffer = CALLOC_STRUCT(nvc0_video_buffer);
559 if (!buffer)
560 return NULL;
561
562 buffer->base.buffer_format = templat->buffer_format;
563 buffer->base.context = pipe;
564 buffer->base.destroy = nvc0_video_buffer_destroy;
565 buffer->base.chroma_format = templat->chroma_format;
566 buffer->base.width = templat->width;
567 buffer->base.height = templat->height;
568 buffer->base.get_sampler_view_planes = nvc0_video_buffer_sampler_view_planes;
569 buffer->base.get_sampler_view_components = nvc0_video_buffer_sampler_view_components;
570 buffer->base.get_surfaces = nvc0_video_buffer_surfaces;
571 buffer->base.interlaced = true;
572
573 memset(&templ, 0, sizeof(templ));
574 templ.target = PIPE_TEXTURE_2D_ARRAY;
575 templ.depth0 = 1;
576 templ.bind = PIPE_BIND_SAMPLER_VIEW | PIPE_BIND_RENDER_TARGET;
577 templ.format = PIPE_FORMAT_R8_UNORM;
578 templ.width0 = buffer->base.width;
579 templ.height0 = (buffer->base.height + 1)/2;
580 templ.flags = NVC0_RESOURCE_FLAG_VIDEO;
581 templ.array_size = 2;
582
583 buffer->resources[0] = pipe->screen->resource_create(pipe->screen, &templ);
584 if (!buffer->resources[0])
585 goto error;
586
587 templ.format = PIPE_FORMAT_R8G8_UNORM;
588 buffer->num_planes = 2;
589 templ.width0 = (templ.width0 + 1) / 2;
590 templ.height0 = (templ.height0 + 1) / 2;
591 for (i = 1; i < buffer->num_planes; ++i) {
592 buffer->resources[i] = pipe->screen->resource_create(pipe->screen, &templ);
593 if (!buffer->resources[i])
594 goto error;
595 }
596
597 memset(&sv_templ, 0, sizeof(sv_templ));
598 for (component = 0, i = 0; i < buffer->num_planes; ++i ) {
599 struct pipe_resource *res = buffer->resources[i];
600 unsigned nr_components = util_format_get_nr_components(res->format);
601
602 u_sampler_view_default_template(&sv_templ, res, res->format);
603 buffer->sampler_view_planes[i] = pipe->create_sampler_view(pipe, res, &sv_templ);
604 if (!buffer->sampler_view_planes[i])
605 goto error;
606
607 for (j = 0; j < nr_components; ++j, ++component) {
608 sv_templ.swizzle_r = sv_templ.swizzle_g = sv_templ.swizzle_b = PIPE_SWIZZLE_RED + j;
609 sv_templ.swizzle_a = PIPE_SWIZZLE_ONE;
610
611 buffer->sampler_view_components[component] = pipe->create_sampler_view(pipe, res, &sv_templ);
612 if (!buffer->sampler_view_components[component])
613 goto error;
614 }
615 }
616
617 memset(&surf_templ, 0, sizeof(surf_templ));
618 for (j = 0; j < buffer->num_planes; ++j) {
619 surf_templ.format = buffer->resources[j]->format;
620 surf_templ.u.tex.first_layer = surf_templ.u.tex.last_layer = 0;
621 buffer->surfaces[j * 2] = pipe->create_surface(pipe, buffer->resources[j], &surf_templ);
622 if (!buffer->surfaces[j * 2])
623 goto error;
624
625 surf_templ.u.tex.first_layer = surf_templ.u.tex.last_layer = 1;
626 buffer->surfaces[j * 2 + 1] = pipe->create_surface(pipe, buffer->resources[j], &surf_templ);
627 if (!buffer->surfaces[j * 2 + 1])
628 goto error;
629 }
630
631 return &buffer->base;
632
633 error:
634 nvc0_video_buffer_destroy(&buffer->base);
635 return NULL;
636 }