Example #1
0
/* Upload data for a particular image.
 */
void
st_texture_image_data(struct st_context *st,
                      struct pipe_resource *dst,
                      GLuint face,
                      GLuint level,
                      void *src,
                      GLuint src_row_stride, GLuint src_image_stride)
{
   struct pipe_context *pipe = st->pipe;
   GLuint i;
   const GLubyte *srcUB = src;
   GLuint layers;

   if (dst->target == PIPE_TEXTURE_1D_ARRAY ||
       dst->target == PIPE_TEXTURE_2D_ARRAY ||
       dst->target == PIPE_TEXTURE_CUBE_ARRAY)
      layers = dst->array_size;
   else
      layers = u_minify(dst->depth0, level);

   DBG("%s\n", __FUNCTION__);

   for (i = 0; i < layers; i++) {
      struct pipe_box box;
      u_box_2d_zslice(0, 0, face + i,
                      u_minify(dst->width0, level),
                      u_minify(dst->height0, level),
                      &box);

      pipe->transfer_inline_write(pipe, dst, level, PIPE_TRANSFER_WRITE,
                                  &box, srcUB, src_row_stride, 0);

      srcUB += src_image_stride;
   }
}
Example #2
0
void renderer_copy_surface(struct renderer *ctx,
                           struct pipe_surface *src,
                           int srcX0, int srcY0,
                           int srcX1, int srcY1,
                           struct pipe_surface *dst,
                           int dstX0, int dstY0,
                           int dstX1, int dstY1,
                           float z, unsigned filter)
{
   struct pipe_context *pipe = ctx->pipe;
   struct pipe_screen *screen = pipe->screen;
   struct pipe_sampler_view view_templ;
   struct pipe_sampler_view *view;
   struct pipe_box src_box;
   struct pipe_resource texTemp, *tex;
   const struct pipe_framebuffer_state *fb = &ctx->g3d.fb;
   const int srcW = abs(srcX1 - srcX0);
   const int srcH = abs(srcY1 - srcY0);
   const int srcLeft = MIN2(srcX0, srcX1);
   const int srcTop = MIN2(srcY0, srcY1);

   assert(filter == PIPE_TEX_MIPFILTER_NEAREST ||
          filter == PIPE_TEX_MIPFILTER_LINEAR);

   if (srcLeft != srcX0) {
      /* left-right flip */
      int tmp = dstX0;
      dstX0 = dstX1;
      dstX1 = tmp;
   }

   if (srcTop != srcY0) {
      /* up-down flip */
      int tmp = dstY0;
      dstY0 = dstY1;
      dstY1 = tmp;
   }

   assert(screen->is_format_supported(screen, src->format, PIPE_TEXTURE_2D,
                                      0, PIPE_BIND_SAMPLER_VIEW));
   assert(screen->is_format_supported(screen, dst->format, PIPE_TEXTURE_2D,
                                      0, PIPE_BIND_SAMPLER_VIEW));
   assert(screen->is_format_supported(screen, dst->format, PIPE_TEXTURE_2D,
                                      0, PIPE_BIND_RENDER_TARGET));

   /*
    * XXX for now we're always creating a temporary texture.
    * Strictly speaking that's not always needed.
    */

   /* create temp texture */
   memset(&texTemp, 0, sizeof(texTemp));
   texTemp.target = PIPE_TEXTURE_2D;
   texTemp.format = src->format;
   texTemp.last_level = 0;
   texTemp.width0 = srcW;
   texTemp.height0 = srcH;
   texTemp.depth0 = 1;
   texTemp.array_size = 1;
   texTemp.bind = PIPE_BIND_SAMPLER_VIEW;

   tex = screen->resource_create(screen, &texTemp);
   if (!tex)
      return;

   u_sampler_view_default_template(&view_templ, tex, tex->format);
   view = pipe->create_sampler_view(pipe, tex, &view_templ);

   if (!view)
      return;

   u_box_2d_zslice(srcLeft, srcTop, src->u.tex.first_layer, srcW, srcH, &src_box);

   pipe->resource_copy_region(pipe,
                              tex, 0, 0, 0, 0,  /* dest */
                              src->texture, 0, &src_box);

   assert(floatsEqual(z, 0.0f));

   /* draw */
   if (fb->cbufs[0] == dst) {
      /* transform back to surface coordinates */
      dstY0 = dst->height - dstY0;
      dstY1 = dst->height - dstY1;

      if (renderer_drawtex_begin(ctx, view)) {
         renderer_drawtex(ctx,
               dstX0, dstY0, dstX1 - dstX0, dstY1 - dstY0,
               0, 0, view->texture->width0, view->texture->height0);
         renderer_drawtex_end(ctx);
      }
   }
   else {
      if (renderer_copy_begin(ctx, dst, VG_TRUE, view)) {
         renderer_copy(ctx,
               dstX0, dstY0, dstX1 - dstX0, dstY1 - dstY0,
               0, 0, view->texture->width0, view->texture->height0);
         renderer_copy_end(ctx);
      }
   }
}
Example #3
0
/**
 * Do a CopyTex[Sub]Image1/2/3D() using a hardware (blit) path if possible.
 * Note that the region to copy has already been clipped so we know we
 * won't read from outside the source renderbuffer's bounds.
 *
 * Note: srcY=0=Bottom of renderbuffer (GL convention)
 */
static void
st_CopyTexSubImage(struct gl_context *ctx, GLuint dims,
                   struct gl_texture_image *texImage,
                   GLint destX, GLint destY, GLint destZ,
                   struct gl_renderbuffer *rb,
                   GLint srcX, GLint srcY, GLsizei width, GLsizei height)
{
   struct st_texture_image *stImage = st_texture_image(texImage);
   const GLenum texBaseFormat = texImage->_BaseFormat;
   struct st_renderbuffer *strb = st_renderbuffer(rb);
   struct st_context *st = st_context(ctx);
   struct pipe_context *pipe = st->pipe;
   struct pipe_screen *screen = pipe->screen;
   enum pipe_format dest_format, src_format;
   GLboolean matching_base_formats;
   GLuint color_writemask, zs_writemask, sample_count;
   struct pipe_surface *dest_surface = NULL;
   GLboolean do_flip = (st_fb_orientation(ctx->ReadBuffer) == Y_0_TOP);
   struct pipe_surface surf_tmpl;
   unsigned int dst_usage;
   GLint srcY0, srcY1;

   /* make sure finalize_textures has been called? 
    */
   if (0) st_validate_state(st);

   if (!strb || !strb->surface || !stImage->pt) {
      debug_printf("%s: null strb or stImage\n", __FUNCTION__);
      return;
   }

   sample_count = strb->surface->texture->nr_samples;
   /* I believe this would be legal, presumably would need to do a resolve
      for color, and for depth/stencil spec says to just use one of the
      depth/stencil samples per pixel? Need some transfer clarifications. */
   assert(sample_count < 2);

   assert(strb);
   assert(strb->surface);
   assert(stImage->pt);

   src_format = strb->surface->format;
   dest_format = stImage->pt->format;

   /*
    * Determine if the src framebuffer and dest texture have the same
    * base format.  We need this to detect a case such as the framebuffer
    * being GL_RGBA but the texture being GL_RGB.  If the actual hardware
    * texture format stores RGBA we need to set A=1 (overriding the
    * framebuffer's alpha values).  We can't do that with the blit or
    * textured-quad paths.
    */
   matching_base_formats =
      (_mesa_get_format_base_format(strb->Base.Format) ==
       _mesa_get_format_base_format(texImage->TexFormat));

   if (ctx->_ImageTransferState) {
      goto fallback;
   }

   if (texImage->TexObject->Target == GL_TEXTURE_1D_ARRAY) {
      /* 1D arrays might be thought of as 2D images but the actual layout
       * might not be that way.  At some points, we convert OpenGL's 1D
       * array 'height' into gallium 'layers' and that prevents the blit
       * utility code from doing the right thing.  Simpy use the memcpy-based
       * fallback.
       */
      goto fallback;
   }

   if (matching_base_formats &&
       src_format == dest_format &&
       !do_flip) {
      /* use surface_copy() / blit */
      struct pipe_box src_box;
      unsigned dstLevel;

      u_box_2d_zslice(srcX, srcY, strb->surface->u.tex.first_layer,
                      width, height, &src_box);

      /* If stImage->pt is an independent image (not a pointer into a full
       * mipmap) stImage->pt.last_level will be zero and we need to use that
       * as the dest level.
       */
      dstLevel = MIN2(stImage->base.Level, stImage->pt->last_level);

      /* for resource_copy_region(), y=0=top, always */
      pipe->resource_copy_region(pipe,
                                 /* dest */
                                 stImage->pt,
                                 dstLevel,
                                 destX, destY, destZ + stImage->base.Face,
                                 /* src */
                                 strb->texture,
                                 strb->surface->u.tex.level,
                                 &src_box);
      return;
   }

   if (texBaseFormat == GL_DEPTH_STENCIL) {
      goto fallback;
   }

   if (texBaseFormat == GL_DEPTH_COMPONENT) {
      color_writemask = 0;
      zs_writemask = BLIT_WRITEMASK_Z;
      dst_usage = PIPE_BIND_DEPTH_STENCIL;
   }
   else {
      color_writemask = compatible_src_dst_formats(ctx, &strb->Base, texImage);
      zs_writemask = 0;
      dst_usage = PIPE_BIND_RENDER_TARGET;
   }

   if ((!color_writemask && !zs_writemask) ||
       !screen->is_format_supported(screen, src_format,
                                    PIPE_TEXTURE_2D, sample_count,
                                    PIPE_BIND_SAMPLER_VIEW) ||
       !screen->is_format_supported(screen, dest_format,
                                    PIPE_TEXTURE_2D, 0,
                                    dst_usage)) {
      goto fallback;
   }

   if (do_flip) {
      srcY1 = strb->Base.Height - srcY - height;
      srcY0 = srcY1 + height;
   }
   else {
      srcY0 = srcY;
      srcY1 = srcY0 + height;
   }

   /* Disable conditional rendering. */
   if (st->render_condition) {
      pipe->render_condition(pipe, NULL, 0);
   }

   memset(&surf_tmpl, 0, sizeof(surf_tmpl));
   surf_tmpl.format = util_format_linear(stImage->pt->format);
   surf_tmpl.usage = dst_usage;
   surf_tmpl.u.tex.level = stImage->base.Level;
   surf_tmpl.u.tex.first_layer = stImage->base.Face + destZ;
   surf_tmpl.u.tex.last_layer = stImage->base.Face + destZ;

   dest_surface = pipe->create_surface(pipe, stImage->pt,
                                       &surf_tmpl);
   util_blit_pixels(st->blit,
                    strb->texture,
                    strb->surface->u.tex.level,
                    srcX, srcY0,
                    srcX + width, srcY1,
                    strb->surface->u.tex.first_layer,
                    dest_surface,
                    destX, destY,
                    destX + width, destY + height,
                    0.0, PIPE_TEX_MIPFILTER_NEAREST,
                    color_writemask, zs_writemask);
   pipe_surface_reference(&dest_surface, NULL);

   /* Restore conditional rendering state. */
   if (st->render_condition) {
      pipe->render_condition(pipe, st->render_condition,
                             st->condition_mode);
   }

   return;

fallback:
   /* software fallback */
   fallback_copy_texsubimage(ctx,
                             strb, stImage, texBaseFormat,
                             destX, destY, destZ,
                             srcX, srcY, width, height);
}
Example #4
0
/* When this function is called, we have already checked
 * The copy regions fit the surfaces */
void
NineSurface9_CopyMemToDefault( struct NineSurface9 *This,
                               struct NineSurface9 *From,
                               const POINT *pDestPoint,
                               const RECT *pSourceRect )
{
    struct pipe_context *pipe = This->pipe;
    struct pipe_transfer *transfer = NULL;
    struct pipe_resource *r_dst = This->base.resource;
    struct pipe_box dst_box;
    uint8_t *map = NULL;
    int src_x, src_y, dst_x, dst_y, copy_width, copy_height;

    assert(This->base.pool == D3DPOOL_DEFAULT &&
           From->base.pool == D3DPOOL_SYSTEMMEM);

    if (pDestPoint) {
        dst_x = pDestPoint->x;
        dst_y = pDestPoint->y;
    } else {
        dst_x = 0;
        dst_y = 0;
    }

    if (pSourceRect) {
        src_x = pSourceRect->left;
        src_y = pSourceRect->top;
        copy_width = pSourceRect->right - pSourceRect->left;
        copy_height = pSourceRect->bottom - pSourceRect->top;
    } else {
        src_x = 0;
        src_y = 0;
        copy_width = From->desc.Width;
        copy_height = From->desc.Height;
    }

    u_box_2d_zslice(dst_x, dst_y, This->layer,
                    copy_width, copy_height, &dst_box);

    map = pipe->transfer_map(pipe,
                             r_dst,
                             This->level,
                             PIPE_TRANSFER_WRITE | PIPE_TRANSFER_DISCARD_RANGE,
                             &dst_box, &transfer);
    if (!map)
        return;

    /* Note: if formats are the sames, it will revert
     * to normal memcpy */
    (void) util_format_translate(r_dst->format,
                                 map, transfer->stride,
                                 0, 0,
                                 From->base.info.format,
                                 From->data, From->stride,
                                 src_x, src_y,
                                 copy_width, copy_height);

    pipe_transfer_unmap(pipe, transfer);

    if (This->data_conversion)
        (void) util_format_translate(This->format_conversion,
                                     This->data_conversion,
                                     This->stride_conversion,
                                     dst_x, dst_y,
                                     From->base.info.format,
                                     From->data, From->stride,
                                     src_x, src_y,
                                     copy_width, copy_height);

    NineSurface9_MarkContainerDirty(This);
}
Example #5
0
/**
 * Do a CopyTex[Sub]Image1/2/3D() using a hardware (blit) path if possible.
 * Note that the region to copy has already been clipped so we know we
 * won't read from outside the source renderbuffer's bounds.
 *
 * Note: srcY=0=Bottom of renderbuffer (GL convention)
 */
static void
st_copy_texsubimage(struct gl_context *ctx,
                    struct gl_texture_image *texImage,
                    GLint destX, GLint destY, GLint destZ,
                    struct gl_renderbuffer *rb,
                    GLint srcX, GLint srcY,
                    GLsizei width, GLsizei height)
{
   struct st_texture_image *stImage = st_texture_image(texImage);
   const GLenum texBaseFormat = texImage->_BaseFormat;
   struct gl_framebuffer *fb = ctx->ReadBuffer;
   struct st_renderbuffer *strb;
   struct st_context *st = st_context(ctx);
   struct pipe_context *pipe = st->pipe;
   struct pipe_screen *screen = pipe->screen;
   enum pipe_format dest_format, src_format;
   GLboolean matching_base_formats;
   GLuint format_writemask, sample_count;
   struct pipe_surface *dest_surface = NULL;
   GLboolean do_flip = (st_fb_orientation(ctx->ReadBuffer) == Y_0_TOP);
   struct pipe_surface surf_tmpl;
   unsigned int dst_usage;
   GLint srcY0, srcY1;

   /* make sure finalize_textures has been called? 
    */
   if (0) st_validate_state(st);

   /* determine if copying depth or color data */
   if (texBaseFormat == GL_DEPTH_COMPONENT ||
       texBaseFormat == GL_DEPTH_STENCIL) {
      strb = st_renderbuffer(fb->Attachment[BUFFER_DEPTH].Renderbuffer);
   }
   else {
      /* texBaseFormat == GL_RGB, GL_RGBA, GL_ALPHA, etc */
      strb = st_renderbuffer(fb->_ColorReadBuffer);
   }

   if (!strb || !strb->surface || !stImage->pt) {
      debug_printf("%s: null strb or stImage\n", __FUNCTION__);
      return;
   }

   sample_count = strb->surface->texture->nr_samples;
   /* I believe this would be legal, presumably would need to do a resolve
      for color, and for depth/stencil spec says to just use one of the
      depth/stencil samples per pixel? Need some transfer clarifications. */
   assert(sample_count < 2);

   assert(strb);
   assert(strb->surface);
   assert(stImage->pt);

   src_format = strb->surface->format;
   dest_format = stImage->pt->format;

   /*
    * Determine if the src framebuffer and dest texture have the same
    * base format.  We need this to detect a case such as the framebuffer
    * being GL_RGBA but the texture being GL_RGB.  If the actual hardware
    * texture format stores RGBA we need to set A=1 (overriding the
    * framebuffer's alpha values).  We can't do that with the blit or
    * textured-quad paths.
    */
   matching_base_formats =
      (_mesa_get_format_base_format(strb->Base.Format) ==
       _mesa_get_format_base_format(texImage->TexFormat));

   if (ctx->_ImageTransferState) {
      goto fallback;
   }

   if (matching_base_formats &&
       src_format == dest_format &&
       !do_flip) {
      /* use surface_copy() / blit */
      struct pipe_box src_box;
      u_box_2d_zslice(srcX, srcY, strb->surface->u.tex.first_layer,
                      width, height, &src_box);

      /* for resource_copy_region(), y=0=top, always */
      pipe->resource_copy_region(pipe,
                                 /* dest */
                                 stImage->pt,
                                 stImage->base.Level,
                                 destX, destY, destZ + stImage->base.Face,
                                 /* src */
                                 strb->texture,
                                 strb->surface->u.tex.level,
                                 &src_box);
      return;
   }

   if (texBaseFormat == GL_DEPTH_STENCIL) {
      goto fallback;
   }

   if (texBaseFormat == GL_DEPTH_COMPONENT) {
      format_writemask = TGSI_WRITEMASK_XYZW;
      dst_usage = PIPE_BIND_DEPTH_STENCIL;
   }
   else {
      format_writemask = compatible_src_dst_formats(ctx, &strb->Base, texImage);
      dst_usage = PIPE_BIND_RENDER_TARGET;
   }

   if (!format_writemask ||
       !screen->is_format_supported(screen, src_format,
                                    PIPE_TEXTURE_2D, sample_count,
                                    PIPE_BIND_SAMPLER_VIEW) ||
       !screen->is_format_supported(screen, dest_format,
                                    PIPE_TEXTURE_2D, 0,
                                    dst_usage)) {
      goto fallback;
   }

   if (do_flip) {
      srcY1 = strb->Base.Height - srcY - height;
      srcY0 = srcY1 + height;
   }
   else {
      srcY0 = srcY;
      srcY1 = srcY0 + height;
   }

   /* Disable conditional rendering. */
   if (st->render_condition) {
      pipe->render_condition(pipe, NULL, 0);
   }

   memset(&surf_tmpl, 0, sizeof(surf_tmpl));
   surf_tmpl.format = util_format_linear(stImage->pt->format);
   surf_tmpl.usage = dst_usage;
   surf_tmpl.u.tex.level = stImage->base.Level;
   surf_tmpl.u.tex.first_layer = stImage->base.Face + destZ;
   surf_tmpl.u.tex.last_layer = stImage->base.Face + destZ;

   dest_surface = pipe->create_surface(pipe, stImage->pt,
                                       &surf_tmpl);
   util_blit_pixels_writemask(st->blit,
                              strb->texture,
                              strb->surface->u.tex.level,
                              srcX, srcY0,
                              srcX + width, srcY1,
                              strb->surface->u.tex.first_layer,
                              dest_surface,
                              destX, destY,
                              destX + width, destY + height,
                              0.0, PIPE_TEX_MIPFILTER_NEAREST,
                              format_writemask);
   pipe_surface_reference(&dest_surface, NULL);

   /* Restore conditional rendering state. */
   if (st->render_condition) {
      pipe->render_condition(pipe, st->render_condition,
                             st->condition_mode);
   }

   return;

fallback:
   /* software fallback */
   fallback_copy_texsubimage(ctx,
                             strb, stImage, texBaseFormat,
                             destX, destY, destZ,
                             srcX, srcY, width, height);
}