radeonsi: Pixel shaders pre-load one more SGPR
[mesa.git] / src / gallium / drivers / nvc0 / nvc0_video.c
index 9d7a823756247da475b652fb8da7ca74b8f0b573..5891f0909d600d9f4b9618f74c32166bdc23ff19 100644 (file)
  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
- * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
- * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
  */
 
 #include "nvc0_video.h"
 #include "util/u_sampler.h"
 #include "util/u_format.h"
 
-#include <sys/mman.h>
-#include <fcntl.h>
-
-int
-nvc0_screen_get_video_param(struct pipe_screen *pscreen,
-                            enum pipe_video_profile profile,
-                            enum pipe_video_cap param)
-{
-   switch (param) {
-   case PIPE_VIDEO_CAP_SUPPORTED:
-      return profile >= PIPE_VIDEO_PROFILE_MPEG1;
-   case PIPE_VIDEO_CAP_NPOT_TEXTURES:
-      return 1;
-   case PIPE_VIDEO_CAP_MAX_WIDTH:
-   case PIPE_VIDEO_CAP_MAX_HEIGHT:
-      return nouveau_screen(pscreen)->device->chipset < 0xd0 ? 2048 : 4096;
-   case PIPE_VIDEO_CAP_PREFERED_FORMAT:
-      return PIPE_FORMAT_NV12;
-   case PIPE_VIDEO_CAP_SUPPORTS_INTERLACED:
-   case PIPE_VIDEO_CAP_PREFERS_INTERLACED:
-      return true;
-   case PIPE_VIDEO_CAP_SUPPORTS_PROGRESSIVE:
-      return false;
-   default:
-      debug_printf("unknown video param: %d\n", param);
-      return 0;
-   }
-}
-
 static void
 nvc0_decoder_decode_bitstream(struct pipe_video_decoder *decoder,
                               struct pipe_video_buffer *video_target,
@@ -62,13 +33,13 @@ nvc0_decoder_decode_bitstream(struct pipe_video_decoder *decoder,
                               const void *const *data,
                               const unsigned *num_bytes)
 {
-   struct nvc0_decoder *dec = (struct nvc0_decoder *)decoder;
-   struct nvc0_video_buffer *target = (struct nvc0_video_buffer *)video_target;
+   struct nouveau_vp3_decoder *dec = (struct nouveau_vp3_decoder *)decoder;
+   struct nouveau_vp3_video_buffer *target = (struct nouveau_vp3_video_buffer *)video_target;
    uint32_t comm_seq = ++dec->fence_seq;
    union pipe_desc desc;
 
    unsigned vp_caps, is_ref, ret;
-   struct nvc0_video_buffer *refs[16] = {};
+   struct nouveau_vp3_video_buffer *refs[16] = {};
 
    desc.base = picture;
 
@@ -85,85 +56,6 @@ nvc0_decoder_decode_bitstream(struct pipe_video_decoder *decoder,
    nvc0_decoder_ppp(dec, desc, target, comm_seq);
 }
 
-static void
-nvc0_decoder_flush(struct pipe_video_decoder *decoder)
-{
-   struct nvc0_decoder *dec = (struct nvc0_decoder *)decoder;
-   (void)dec;
-}
-
-static void
-nvc0_decoder_begin_frame(struct pipe_video_decoder *decoder,
-                         struct pipe_video_buffer *target,
-                         struct pipe_picture_desc *picture)
-{
-}
-
-static void
-nvc0_decoder_end_frame(struct pipe_video_decoder *decoder,
-                       struct pipe_video_buffer *target,
-                       struct pipe_picture_desc *picture)
-{
-}
-
-static void
-nvc0_decoder_destroy(struct pipe_video_decoder *decoder)
-{
-   struct nvc0_decoder *dec = (struct nvc0_decoder *)decoder;
-   int i;
-
-   nouveau_bo_ref(NULL, &dec->ref_bo);
-   nouveau_bo_ref(NULL, &dec->bitplane_bo);
-   nouveau_bo_ref(NULL, &dec->inter_bo[0]);
-   nouveau_bo_ref(NULL, &dec->inter_bo[1]);
-#ifdef NVC0_DEBUG_FENCE
-   nouveau_bo_ref(NULL, &dec->fence_bo);
-#endif
-   nouveau_bo_ref(NULL, &dec->fw_bo);
-
-   for (i = 0; i < NVC0_VIDEO_QDEPTH; ++i)
-      nouveau_bo_ref(NULL, &dec->bsp_bo[i]);
-
-   nouveau_object_del(&dec->bsp);
-   nouveau_object_del(&dec->vp);
-   nouveau_object_del(&dec->ppp);
-
-   if (dec->channel[0] != dec->channel[1]) {
-      for (i = 0; i < 3; ++i) {
-         nouveau_pushbuf_del(&dec->pushbuf[i]);
-         nouveau_object_del(&dec->channel[i]);
-      }
-   } else {
-      nouveau_pushbuf_del(dec->pushbuf);
-      nouveau_object_del(dec->channel);
-   }
-
-   FREE(dec);
-}
-
-static void nvc0_video_getpath(enum pipe_video_profile profile, char *path)
-{
-   switch (u_reduce_video_profile(profile)) {
-      case PIPE_VIDEO_CODEC_MPEG12: {
-         sprintf(path, "/lib/firmware/nouveau/vuc-mpeg12-0");
-         break;
-      }
-      case PIPE_VIDEO_CODEC_MPEG4: {
-         sprintf(path, "/lib/firmware/nouveau/vuc-mpeg4-0");
-         break;
-      }
-      case PIPE_VIDEO_CODEC_VC1: {
-         sprintf(path, "/lib/firmware/nouveau/vuc-vc1-%u", profile - PIPE_VIDEO_PROFILE_VC1_SIMPLE);
-         break;
-      }
-      case PIPE_VIDEO_CODEC_MPEG4_AVC: {
-         sprintf(path, "/lib/firmware/nouveau/vuc-h264-0");
-         break;
-      }
-      default: assert(0);
-   }
-}
-
 struct pipe_video_decoder *
 nvc0_create_decoder(struct pipe_context *context,
                     enum pipe_video_profile profile,
@@ -173,7 +65,7 @@ nvc0_create_decoder(struct pipe_context *context,
                     bool chunked_decode)
 {
    struct nouveau_screen *screen = &((struct nvc0_context *)context)->screen->base;
-   struct nvc0_decoder *dec;
+   struct nouveau_vp3_decoder *dec;
    struct nouveau_pushbuf **push;
    union nouveau_bo_config cfg;
    bool kepler = screen->device->chipset >= 0xe0;
@@ -196,10 +88,11 @@ nvc0_create_decoder(struct pipe_context *context,
       return NULL;
    }
 
-   dec = CALLOC_STRUCT(nvc0_decoder);
+   dec = CALLOC_STRUCT(nouveau_vp3_decoder);
    if (!dec)
       return NULL;
    dec->client = screen->client;
+   nouveau_vp3_decoder_init_common(&dec->base);
 
    if (!kepler) {
       dec->bsp_idx = 5;
@@ -282,13 +175,9 @@ nvc0_create_decoder(struct pipe_context *context,
    dec->base.width = width;
    dec->base.height = height;
    dec->base.max_references = max_references;
-   dec->base.destroy = nvc0_decoder_destroy;
-   dec->base.flush = nvc0_decoder_flush;
    dec->base.decode_bitstream = nvc0_decoder_decode_bitstream;
-   dec->base.begin_frame = nvc0_decoder_begin_frame;
-   dec->base.end_frame = nvc0_decoder_end_frame;
 
-   for (i = 0; i < NVC0_VIDEO_QDEPTH && !ret; ++i)
+   for (i = 0; i < NOUVEAU_VP3_VIDEO_QDEPTH && !ret; ++i)
       ret = nouveau_bo_new(screen->device, NOUVEAU_BO_VRAM,
                            0, 1 << 20, &cfg, &dec->bsp_bo[i]);
    if (!ret)
@@ -325,7 +214,7 @@ nvc0_create_decoder(struct pipe_context *context,
    }
    case PIPE_VIDEO_CODEC_MPEG4_AVC: {
       codec = 3;
-      dec->tmp_stride = 16 * mb_half(width) * nvc0_video_align(height) * 3 / 2;
+      dec->tmp_stride = 16 * mb_half(width) * nouveau_vp3_video_align(height) * 3 / 2;
       tmp_size = dec->tmp_stride * (max_references + 1);
       assert(max_references <= 16);
       break;
@@ -336,76 +225,14 @@ nvc0_create_decoder(struct pipe_context *context,
    }
 
    if (screen->device->chipset < 0xd0) {
-      int fd;
-      char path[PATH_MAX];
-      ssize_t r;
-      uint32_t *end, endval;
-
       ret = nouveau_bo_new(screen->device, NOUVEAU_BO_VRAM, 0,
                            0x4000, &cfg, &dec->fw_bo);
-      if (!ret)
-         ret = nouveau_bo_map(dec->fw_bo, NOUVEAU_BO_WR, dec->client);
       if (ret)
          goto fail;
 
-      nvc0_video_getpath(profile, path);
-
-      fd = open(path, O_RDONLY | O_CLOEXEC);
-      if (fd < 0) {
-         fprintf(stderr, "opening firmware file %s failed: %m\n", path);
-         goto fw_fail;
-      }
-      r = read(fd, dec->fw_bo->map, 0x4000);
-      close(fd);
-
-      if (r < 0) {
-         fprintf(stderr, "reading firmware file %s failed: %m\n", path);
-         goto fw_fail;
-      }
-
-      if (r == 0x4000) {
-         fprintf(stderr, "firmware file %s too large!\n", path);
-         goto fw_fail;
-      }
-
-      if (r & 0xff) {
-         fprintf(stderr, "firmware file %s wrong size!\n", path);
-         goto fw_fail;
-      }
-
-      end = dec->fw_bo->map + r - 4;
-      endval = *end;
-      while (endval == *end)
-         end--;
-
-      r = (intptr_t)end - (intptr_t)dec->fw_bo->map + 4;
-
-      switch (u_reduce_video_profile(profile)) {
-      case PIPE_VIDEO_CODEC_MPEG12: {
-         assert((r & 0xff) == 0xe0);
-         dec->fw_sizes = (0x2e0<<16) | (r - 0x2e0);
-         break;
-      }
-      case PIPE_VIDEO_CODEC_MPEG4: {
-         assert((r & 0xff) == 0xe0);
-         dec->fw_sizes = (0x2e0<<16) | (r - 0x2e0);
-         break;
-      }
-      case PIPE_VIDEO_CODEC_VC1: {
-         assert((r & 0xff) == 0xac);
-         dec->fw_sizes = (0x3ac<<16) | (r - 0x3ac);
-         break;
-      }
-      case PIPE_VIDEO_CODEC_MPEG4_AVC: {
-         assert((r & 0xff) == 0x70);
-         dec->fw_sizes = (0x370<<16) | (r - 0x370);
-         break;
-      }
-      default:
+      ret = nouveau_vp3_load_firmware(dec, profile, screen->device->chipset);
+      if (ret)
          goto fw_fail;
-      }
-      munmap(dec->fw_bo->map, dec->fw_bo->size);
-      dec->fw_bo->map = NULL;
    }
 
    if (codec != 3) {
@@ -415,7 +242,7 @@ nvc0_create_decoder(struct pipe_context *context,
          goto fail;
    }
 
-   dec->ref_stride = mb(width)*16 * (mb_half(height)*32 + nvc0_video_align(height)/2);
+   dec->ref_stride = mb(width)*16 * (mb_half(height)*32 + nouveau_vp3_video_align(height)/2);
    ret = nouveau_bo_new(screen->device, NOUVEAU_BO_VRAM, 0,
                         dec->ref_stride * (max_references+2) + tmp_size,
                         &cfg, &dec->ref_bo);
@@ -438,9 +265,9 @@ nvc0_create_decoder(struct pipe_context *context,
 
    ++dec->fence_seq;
 
-#if NVC0_DEBUG_FENCE
+#if NOUVEAU_VP3_DEBUG_FENCE
    ret = nouveau_bo_new(screen->device, NOUVEAU_BO_GART|NOUVEAU_BO_MAP,
-                        0, 0x1000, &cfg, &dec->fence_bo);
+                        0, 0x1000, NULL, &dec->fence_bo);
    if (ret)
       goto fail;
 
@@ -450,36 +277,42 @@ nvc0_create_decoder(struct pipe_context *context,
    dec->comm = (struct comm *)(dec->fence_map + (COMM_OFFSET/sizeof(*dec->fence_map)));
 
    /* So lets test if the fence is working? */
+   nouveau_pushbuf_space(push[0], 6, 1, 0);
+   PUSH_REFN (push[0], dec->fence_bo, NOUVEAU_BO_GART|NOUVEAU_BO_RDWR);
    BEGIN_NVC0(push[0], SUBC_BSP(0x240), 3);
    PUSH_DATAh(push[0], dec->fence_bo->offset);
    PUSH_DATA (push[0], dec->fence_bo->offset);
    PUSH_DATA (push[0], dec->fence_seq);
 
    BEGIN_NVC0(push[0], SUBC_BSP(0x304), 1);
-   PUSH_DATA (push[0], 1);
+   PUSH_DATA (push[0], 0);
    PUSH_KICK (push[0]);
 
+   nouveau_pushbuf_space(push[1], 6, 1, 0);
+   PUSH_REFN (push[1], dec->fence_bo, NOUVEAU_BO_GART|NOUVEAU_BO_RDWR);
    BEGIN_NVC0(push[1], SUBC_VP(0x240), 3);
    PUSH_DATAh(push[1], (dec->fence_bo->offset + 0x10));
    PUSH_DATA (push[1], (dec->fence_bo->offset + 0x10));
    PUSH_DATA (push[1], dec->fence_seq);
 
    BEGIN_NVC0(push[1], SUBC_VP(0x304), 1);
-   PUSH_DATA (push[1], 1);
+   PUSH_DATA (push[1], 0);
    PUSH_KICK (push[1]);
 
+   nouveau_pushbuf_space(push[2], 6, 1, 0);
+   PUSH_REFN (push[2], dec->fence_bo, NOUVEAU_BO_GART|NOUVEAU_BO_RDWR);
    BEGIN_NVC0(push[2], SUBC_PPP(0x240), 3);
    PUSH_DATAh(push[2], (dec->fence_bo->offset + 0x20));
    PUSH_DATA (push[2], (dec->fence_bo->offset + 0x20));
    PUSH_DATA (push[2], dec->fence_seq);
 
    BEGIN_NVC0(push[2], SUBC_PPP(0x304), 1);
-   PUSH_DATA (push[2], 1);
+   PUSH_DATA (push[2], 0);
    PUSH_KICK (push[2]);
 
    usleep(100);
-   while (dec->fence_seq > dec->fence_map[0] &&
-          dec->fence_seq > dec->fence_map[4] &&
+   while (dec->fence_seq > dec->fence_map[0] ||
+          dec->fence_seq > dec->fence_map[4] ||
           dec->fence_seq > dec->fence_map[8]) {
       debug_printf("%u: %u %u %u\n", dec->fence_seq, dec->fence_map[0], dec->fence_map[4], dec->fence_map[8]);
       usleep(100);
@@ -491,149 +324,19 @@ nvc0_create_decoder(struct pipe_context *context,
 
 fw_fail:
    debug_printf("Cannot create decoder without firmware..\n");
-   nvc0_decoder_destroy(&dec->base);
+   dec->base.destroy(&dec->base);
    return NULL;
 
 fail:
    debug_printf("Creation failed: %s (%i)\n", strerror(-ret), ret);
-   nvc0_decoder_destroy(&dec->base);
+   dec->base.destroy(&dec->base);
    return NULL;
 }
 
-static struct pipe_sampler_view **
-nvc0_video_buffer_sampler_view_planes(struct pipe_video_buffer *buffer)
-{
-   struct nvc0_video_buffer *buf = (struct nvc0_video_buffer *)buffer;
-   return buf->sampler_view_planes;
-}
-
-static struct pipe_sampler_view **
-nvc0_video_buffer_sampler_view_components(struct pipe_video_buffer *buffer)
-{
-   struct nvc0_video_buffer *buf = (struct nvc0_video_buffer *)buffer;
-   return buf->sampler_view_components;
-}
-
-static struct pipe_surface **
-nvc0_video_buffer_surfaces(struct pipe_video_buffer *buffer)
-{
-   struct nvc0_video_buffer *buf = (struct nvc0_video_buffer *)buffer;
-   return buf->surfaces;
-}
-
-static void
-nvc0_video_buffer_destroy(struct pipe_video_buffer *buffer)
-{
-   struct nvc0_video_buffer *buf = (struct nvc0_video_buffer *)buffer;
-   unsigned i;
-
-   assert(buf);
-
-   for (i = 0; i < VL_NUM_COMPONENTS; ++i) {
-      pipe_resource_reference(&buf->resources[i], NULL);
-      pipe_sampler_view_reference(&buf->sampler_view_planes[i], NULL);
-      pipe_sampler_view_reference(&buf->sampler_view_components[i], NULL);
-      pipe_surface_reference(&buf->surfaces[i * 2], NULL);
-      pipe_surface_reference(&buf->surfaces[i * 2 + 1], NULL);
-   }
-   FREE(buffer);
-}
-
 struct pipe_video_buffer *
 nvc0_video_buffer_create(struct pipe_context *pipe,
                          const struct pipe_video_buffer *templat)
 {
-   struct nvc0_video_buffer *buffer;
-   struct pipe_resource templ;
-   unsigned i, j, component;
-   struct pipe_sampler_view sv_templ;
-   struct pipe_surface surf_templ;
-
-   assert(templat->interlaced);
-   if (getenv("XVMC_VL") || templat->buffer_format != PIPE_FORMAT_NV12)
-      return vl_video_buffer_create(pipe, templat);
-
-   assert(templat->chroma_format == PIPE_VIDEO_CHROMA_FORMAT_420);
-
-   buffer = CALLOC_STRUCT(nvc0_video_buffer);
-   if (!buffer)
-      return NULL;
-   assert(!(templat->height % 4));
-   assert(!(templat->width % 2));
-
-   buffer->base.buffer_format = templat->buffer_format;
-   buffer->base.context = pipe;
-   buffer->base.destroy = nvc0_video_buffer_destroy;
-   buffer->base.chroma_format = templat->chroma_format;
-   buffer->base.width = templat->width;
-   buffer->base.height = templat->height;
-   buffer->base.get_sampler_view_planes = nvc0_video_buffer_sampler_view_planes;
-   buffer->base.get_sampler_view_components = nvc0_video_buffer_sampler_view_components;
-   buffer->base.get_surfaces = nvc0_video_buffer_surfaces;
-   buffer->base.interlaced = true;
-
-   memset(&templ, 0, sizeof(templ));
-   templ.target = PIPE_TEXTURE_3D;
-   templ.depth0 = 2;
-   templ.bind = PIPE_BIND_SAMPLER_VIEW | PIPE_BIND_RENDER_TARGET;
-   templ.format = PIPE_FORMAT_R8_UNORM;
-   templ.width0 = buffer->base.width;
-   templ.height0 = buffer->base.height/2;
-   templ.flags = NVC0_RESOURCE_FLAG_VIDEO;
-   templ.last_level = 0;
-   templ.array_size = 1;
-
-   buffer->resources[0] = pipe->screen->resource_create(pipe->screen, &templ);
-   if (!buffer->resources[0])
-      goto error;
-
-   templ.format = PIPE_FORMAT_R8G8_UNORM;
-   buffer->num_planes = 2;
-   templ.width0 /= 2;
-   templ.height0 /= 2;
-   for (i = 1; i < buffer->num_planes; ++i) {
-      buffer->resources[i] = pipe->screen->resource_create(pipe->screen, &templ);
-      if (!buffer->resources[i])
-         goto error;
-   }
-
-   memset(&sv_templ, 0, sizeof(sv_templ));
-   for (component = 0, i = 0; i < buffer->num_planes; ++i ) {
-      struct pipe_resource *res = buffer->resources[i];
-      unsigned nr_components = util_format_get_nr_components(res->format);
-
-      u_sampler_view_default_template(&sv_templ, res, res->format);
-      buffer->sampler_view_planes[i] = pipe->create_sampler_view(pipe, res, &sv_templ);
-      if (!buffer->sampler_view_planes[i])
-         goto error;
-
-      for (j = 0; j < nr_components; ++j, ++component) {
-         sv_templ.swizzle_r = sv_templ.swizzle_g = sv_templ.swizzle_b = PIPE_SWIZZLE_RED + j;
-         sv_templ.swizzle_a = PIPE_SWIZZLE_ONE;
-
-         buffer->sampler_view_components[component] = pipe->create_sampler_view(pipe, res, &sv_templ);
-         if (!buffer->sampler_view_components[component])
-            goto error;
-      }
-  }
-
-   memset(&surf_templ, 0, sizeof(surf_templ));
-   for (j = 0; j < buffer->num_planes; ++j) {
-      surf_templ.format = buffer->resources[j]->format;
-      surf_templ.u.tex.first_layer = surf_templ.u.tex.last_layer = 0;
-      buffer->surfaces[j * 2] = pipe->create_surface(pipe, buffer->resources[j], &surf_templ);
-      if (!buffer->surfaces[j * 2])
-         goto error;
-
-      surf_templ.u.tex.first_layer = surf_templ.u.tex.last_layer = 1;
-      buffer->surfaces[j * 2 + 1] = pipe->create_surface(pipe, buffer->resources[j], &surf_templ);
-      if (!buffer->surfaces[j * 2 + 1])
-         goto error;
-   }
-
-   return &buffer->base;
-
-error:
-   nvc0_video_buffer_destroy(&buffer->base);
-   return NULL;
+   return nouveau_vp3_video_buffer_create(
+         pipe, templat, NVC0_RESOURCE_FLAG_VIDEO);
 }