Пример #1
0
static boolean
vg_context_update_color_rb(struct vg_context *ctx, struct pipe_resource *pt)
{
    struct st_renderbuffer *strb = ctx->draw_buffer->strb;
    struct pipe_context *pipe = ctx->pipe;
    struct pipe_surface surf_tmpl;

    if (strb->texture == pt) {
        pipe_resource_reference(&pt, NULL);
        return FALSE;
    }

    /* unreference existing ones */
    pipe_surface_reference(&strb->surface, NULL);
    pipe_resource_reference(&strb->texture, NULL);
    strb->width = strb->height = 0;

    strb->texture = pt;

    u_surface_default_template(&surf_tmpl, strb->texture);
    strb->surface = pipe->create_surface(pipe, strb->texture, &surf_tmpl);

    if (!strb->surface) {
        pipe_resource_reference(&strb->texture, NULL);
        return TRUE;
    }

    strb->width = pt->width0;
    strb->height = pt->height0;

    return TRUE;
}
Пример #2
0
int
xa_ctx_srf_create(struct xa_context *ctx, struct xa_surface *dst)
{
    struct pipe_screen *screen = ctx->pipe->screen;
    struct pipe_surface srf_templ;

    /*
     * Cache surfaces unless we change render target
     */
    if (ctx->srf) {
        if (ctx->srf->texture == dst->tex)
            return XA_ERR_NONE;

        pipe_surface_reference(&ctx->srf, NULL);
    }

    if (!screen->is_format_supported(screen,  dst->tex->format,
				     PIPE_TEXTURE_2D, 0,
				     PIPE_BIND_RENDER_TARGET))
	return -XA_ERR_INVAL;

    u_surface_default_template(&srf_templ, dst->tex);
    ctx->srf = ctx->pipe->create_surface(ctx->pipe, dst->tex, &srf_templ);
    if (!ctx->srf)
	return -XA_ERR_NORES;

    return XA_ERR_NONE;
}
Пример #3
0
/**
 * Helper to quickly create an RGBA rendering surface of a certain size.
 * \param textureOut  returns the new texture
 * \param surfaceOut  returns the new surface
 * \return TRUE for success, FALSE if failure
 */
boolean
util_create_rgba_surface(struct pipe_context *pipe,
                         uint width, uint height,
                         uint bind,
                         struct pipe_resource **textureOut,
                         struct pipe_surface **surfaceOut)
{
   static const enum pipe_format rgbaFormats[] = {
      PIPE_FORMAT_B8G8R8A8_UNORM,
      PIPE_FORMAT_A8R8G8B8_UNORM,
      PIPE_FORMAT_A8B8G8R8_UNORM,
      PIPE_FORMAT_NONE
   };
   const uint target = PIPE_TEXTURE_2D;
   enum pipe_format format = PIPE_FORMAT_NONE;
   struct pipe_resource templ;
   struct pipe_surface surf_templ;
   struct pipe_screen *screen = pipe->screen;
   uint i;

   /* Choose surface format */
   for (i = 0; rgbaFormats[i]; i++) {
      if (screen->is_format_supported(screen, rgbaFormats[i],
                                      target, 0, bind)) {
         format = rgbaFormats[i];
         break;
      }
   }
   if (format == PIPE_FORMAT_NONE)
      return FALSE;  /* unable to get an rgba format!?! */

   /* create texture */
   memset(&templ, 0, sizeof(templ));
   templ.target = target;
   templ.format = format;
   templ.last_level = 0;
   templ.width0 = width;
   templ.height0 = height;
   templ.depth0 = 1;
   templ.array_size = 1;
   templ.bind = bind;

   *textureOut = screen->resource_create(screen, &templ);
   if (!*textureOut)
      return FALSE;

   /* create surface */
   memset(&surf_templ, 0, sizeof(surf_templ));
   u_surface_default_template(&surf_templ, *textureOut, bind);
   /* create surface / view into texture */
   *surfaceOut = pipe->create_surface(pipe,
                                      *textureOut,
                                      &surf_templ);
   if (!*surfaceOut) {
      pipe_resource_reference(textureOut, NULL);
      return FALSE;
   }

   return TRUE;
}
Пример #4
0
/**
 * Return the surface of an EGLImage.
 * FIXME: I think this should operate on resources, not surfaces
 */
struct pipe_surface *
st_manager_get_egl_image_surface(struct st_context *st,
                                 void *eglimg, unsigned usage)
{
   struct st_manager *smapi =
      (struct st_manager *) st->iface.st_context_private;
   struct st_egl_image stimg;
   struct pipe_surface *ps, surf_tmpl;

   if (!smapi || !smapi->get_egl_image)
      return NULL;

   memset(&stimg, 0, sizeof(stimg));
   if (!smapi->get_egl_image(smapi, eglimg, &stimg))
      return NULL;

   u_surface_default_template(&surf_tmpl, stimg.texture, usage);
   surf_tmpl.u.tex.level = stimg.level;
   surf_tmpl.u.tex.first_layer = stimg.layer;
   surf_tmpl.u.tex.last_layer = stimg.layer;
   ps = st->pipe->create_surface(st->pipe, stimg.texture, &surf_tmpl);
   pipe_resource_reference(&stimg.texture, NULL);

   return ps;
}
Пример #5
0
extern int
xa_yuv_planar_blit(struct xa_context *r,
		   int src_x,
		   int src_y,
		   int src_w,
		   int src_h,
		   int dst_x,
		   int dst_y,
		   int dst_w,
		   int dst_h,
		   struct xa_box *box,
		   unsigned int num_boxes,
		   const float conversion_matrix[],
		   struct xa_surface *dst, struct xa_surface *yuv[])
{
    float scale_x;
    float scale_y;
    struct pipe_surface srf_templ;

    if (dst_w == 0 || dst_h == 0)
	return XA_ERR_NONE;

    memset(&srf_templ, 0, sizeof(srf_templ));
    u_surface_default_template(&srf_templ, dst->tex, PIPE_BIND_RENDER_TARGET);
    dst->srf = r->pipe->create_surface(r->pipe, dst->tex, &srf_templ);
    if (!dst->srf)
	return -XA_ERR_NORES;

    renderer_bind_destination(r, dst->srf, dst->srf->width, dst->srf->height);
    xa_yuv_bind_blend_state(r);
    xa_yuv_bind_shaders(r);
    xa_yuv_bind_samplers(r, yuv);
    xa_yuv_fs_constants(r, conversion_matrix);

    scale_x = (float)src_w / (float)dst_w;
    scale_y = (float)src_h / (float)dst_h;

    while (num_boxes--) {
	int x = box->x1;
	int y = box->y1;
	int w = box->x2 - box->x1;
	int h = box->y2 - box->y1;

	renderer_draw_yuv(r,
			  (float)src_x + scale_x * (x - dst_x),
			  (float)src_y + scale_y * (y - dst_y),
			  scale_x * w, scale_y * h, x, y, w, h, yuv);
	box++;
    }

    r->pipe->flush(r->pipe, &r->last_fence);

    xa_yuv_destroy_sampler_views(yuv);
    pipe_surface_reference(&dst->srf, NULL);

    return XA_ERR_NONE;
}
Пример #6
0
void debug_dump_texture(struct pipe_context *pipe,
                        const char *prefix,
                        struct pipe_resource *texture)
{
   struct pipe_surface *surface, surf_tmpl;

   if (!texture)
      return;

   /* XXX for now, just dump image for layer=0, level=0 */
   u_surface_default_template(&surf_tmpl, texture);
   surface = pipe->create_surface(pipe, texture, &surf_tmpl);
   if (surface) {
      debug_dump_surface(pipe, prefix, surface);
      pipe->surface_destroy(pipe, surface);
   }
}
Пример #7
0
void image_set_pixels(VGint dx, VGint dy,
                      struct vg_image *src, VGint sx, VGint sy,
                      VGint width, VGint height)
{
   struct vg_context *ctx = vg_current_context();
   struct pipe_context *pipe = ctx->pipe;
   struct pipe_surface *surf, surf_tmpl;
   struct st_renderbuffer *strb = ctx->draw_buffer->strb;

   memset(&surf_tmpl, 0, sizeof(surf_tmpl));
   u_surface_default_template(&surf_tmpl, image_texture(src),
                              0 /* no bind flag - not a surface*/);
   surf = pipe->create_surface(pipe, image_texture(src), &surf_tmpl);

   vg_copy_surface(ctx, strb->surface, dx, dy,
                   surf, sx+src->x, sy+src->y, width, height);

   pipe->surface_destroy(pipe, surf);
}
Пример #8
0
static void
st_egl_image_target_renderbuffer_storage(struct gl_context *ctx,
					 struct gl_renderbuffer *rb,
					 GLeglImageOES image_handle)
{
   struct st_renderbuffer *strb = st_renderbuffer(rb);
   struct st_egl_image stimg;

   if (st_get_egl_image(ctx, image_handle, PIPE_BIND_RENDER_TARGET,
                        "glEGLImageTargetRenderbufferStorage",
                        &stimg)) {
      struct pipe_context *pipe = st_context(ctx)->pipe;
      struct pipe_surface *ps, surf_tmpl;

      u_surface_default_template(&surf_tmpl, stimg.texture);
      surf_tmpl.format = stimg.format;
      surf_tmpl.u.tex.level = stimg.level;
      surf_tmpl.u.tex.first_layer = stimg.layer;
      surf_tmpl.u.tex.last_layer = stimg.layer;
      ps = pipe->create_surface(pipe, stimg.texture, &surf_tmpl);
      pipe_resource_reference(&stimg.texture, NULL);

      if (!ps)
         return;

      strb->Base.Width = ps->width;
      strb->Base.Height = ps->height;
      strb->Base.Format = st_pipe_format_to_mesa_format(ps->format);
      strb->Base._BaseFormat = st_pipe_format_to_base_format(ps->format);
      strb->Base.InternalFormat = strb->Base._BaseFormat;

      struct pipe_surface **psurf =
         util_format_is_srgb(ps->format) ? &strb->surface_srgb :
                                           &strb->surface_linear;

      pipe_surface_reference(psurf, ps);
      strb->surface = *psurf;
      pipe_resource_reference(&strb->texture, ps->texture);

      pipe_surface_reference(&ps, NULL);
   }
}
Пример #9
0
int
xa_ctx_srf_create(struct xa_context *ctx, struct xa_surface *dst)
{
    struct pipe_screen *screen = ctx->pipe->screen;
    struct pipe_surface srf_templ;

    if (ctx->srf)
	return -XA_ERR_INVAL;

    if (!screen->is_format_supported(screen,  dst->tex->format,
				     PIPE_TEXTURE_2D, 0,
				     PIPE_BIND_RENDER_TARGET))
	return -XA_ERR_INVAL;

    u_surface_default_template(&srf_templ, dst->tex);
    ctx->srf = ctx->pipe->create_surface(ctx->pipe, dst->tex, &srf_templ);
    if (!ctx->srf)
	return -XA_ERR_NORES;

    return XA_ERR_NONE;
}
Пример #10
0
static boolean
vg_context_update_depth_stencil_rb(struct vg_context * ctx,
                                   uint width, uint height)
{
   struct st_renderbuffer *dsrb = ctx->draw_buffer->dsrb;
   struct pipe_context *pipe = ctx->pipe;
   struct pipe_surface surf_tmpl;

   if ((dsrb->width == width && dsrb->height == height) && dsrb->texture)
      return FALSE;

   /* unreference existing ones */
   pipe_surface_reference(&dsrb->surface, NULL);
   pipe_resource_reference(&dsrb->texture, NULL);
   dsrb->width = dsrb->height = 0;

   dsrb->texture = create_texture(pipe, dsrb->format, width, height);
   if (!dsrb->texture)
      return TRUE;

   memset(&surf_tmpl, 0, sizeof(surf_tmpl));
   u_surface_default_template(&surf_tmpl, dsrb->texture,
                              PIPE_BIND_DEPTH_STENCIL);
   dsrb->surface = pipe->create_surface(pipe,
                                        dsrb->texture,
                                        &surf_tmpl);
   if (!dsrb->surface) {
      pipe_resource_reference(&dsrb->texture, NULL);
      return TRUE;
   }

   dsrb->width = width;
   dsrb->height = height;

   assert(dsrb->surface->width == width);
   assert(dsrb->surface->height == height);

   return TRUE;
}
Пример #11
0
void image_get_pixels(struct vg_image *dst, VGint dx, VGint dy,
                      VGint sx, VGint sy,
                      VGint width, VGint height)
{
   struct vg_context *ctx = vg_current_context();
   struct pipe_context *pipe = ctx->pipe;
   struct pipe_surface *surf, surf_tmpl;
   struct st_renderbuffer *strb = ctx->draw_buffer->strb;

   /* flip the y coordinates */
   /*dy = dst->height - dy - height;*/

   memset(&surf_tmpl, 0, sizeof(surf_tmpl));
   u_surface_default_template(&surf_tmpl, image_texture(dst),
                              PIPE_BIND_RENDER_TARGET);
   surf = pipe->create_surface(pipe, image_texture(dst), &surf_tmpl);

   vg_copy_surface(ctx, surf, dst->x + dx, dst->y + dy,
                   strb->surface, sx, sy, width, height);

   pipe_surface_reference(&surf, NULL);
}
Пример #12
0
static void vg_copy_texture(struct vg_context *ctx,
                            struct pipe_resource *dst, VGint dx, VGint dy,
                            struct pipe_sampler_view *src, VGint sx, VGint sy,
                            VGint width, VGint height)
{
   VGfloat dst_loc[4], src_loc[4];

   dst_loc[0] = dx;
   dst_loc[1] = dy;
   dst_loc[2] = width;
   dst_loc[3] = height;

   src_loc[0] = sx;
   src_loc[1] = sy;
   src_loc[2] = width;
   src_loc[3] = height;

   vg_get_copy_coords(src_loc, src->texture->width0, src->texture->height0,
                      dst_loc, dst->width0, dst->height0);

   if (src_loc[2] >= 0 && src_loc[3] >= 0 &&
       dst_loc[2] >= 0 && dst_loc[3] >= 0) {
      struct pipe_surface *surf, surf_tmpl;

      /* get the destination surface */
      u_surface_default_template(&surf_tmpl, dst, PIPE_BIND_RENDER_TARGET);
      surf = ctx->pipe->create_surface(ctx->pipe, dst, &surf_tmpl);
      if (surf && renderer_copy_begin(ctx->renderer, surf, VG_TRUE, src)) {
         renderer_copy(ctx->renderer,
               dst_loc[0], dst_loc[1], dst_loc[2], dst_loc[3],
               src_loc[0], src_loc[1], src_loc[2], src_loc[3]);
         renderer_copy_end(ctx->renderer);
      }

      pipe_surface_reference(&surf, NULL);
   }
}
Пример #13
0
static void vg_prepare_blend_texture(struct vg_context *ctx,
                                     struct pipe_sampler_view *src)
{
   struct st_framebuffer *stfb = ctx->draw_buffer;
   struct pipe_surface *surf;
   struct pipe_surface surf_tmpl;

   vg_context_update_blend_texture_view(ctx, stfb->width, stfb->height);

   memset(&surf_tmpl, 0, sizeof(surf_tmpl));
   u_surface_default_template(&surf_tmpl, stfb->blend_texture_view->texture,
                              PIPE_BIND_RENDER_TARGET);
   surf = ctx->pipe->create_surface(ctx->pipe,
                                    stfb->blend_texture_view->texture,
                                    &surf_tmpl);
   if (surf) {
      util_blit_pixels_tex(ctx->blit,
                           src, 0, 0, stfb->width, stfb->height,
                           surf, 0, 0, stfb->width, stfb->height,
                           0.0, PIPE_TEX_MIPFILTER_NEAREST);

      pipe_surface_reference(&surf, NULL);
   }
}
Пример #14
0
/**
 * Validate a framebuffer to make sure up-to-date pipe_textures are used.
 * The context we need to pass in is s dummy context needed only to be
 * able to get a pipe context to create pipe surfaces, and to have a
 * context to call _mesa_resize_framebuffer():
 * (That should probably be rethought, since those surfaces become
 * drawable state, not context state, and can be freed by another pipe
 * context).
 */
static void
st_framebuffer_validate(struct st_framebuffer *stfb,
                        struct st_context *st)
{
   struct pipe_resource *textures[ST_ATTACHMENT_COUNT];
   uint width, height;
   unsigned i;
   boolean changed = FALSE;
   int32_t new_stamp = p_atomic_read(&stfb->iface->stamp);

   if (stfb->iface_stamp == new_stamp)
      return;

   /* validate the fb */
   do {
      if (!stfb->iface->validate(stfb->iface, stfb->statts,
				 stfb->num_statts, textures))
	 return;

      stfb->iface_stamp = new_stamp;
      new_stamp = p_atomic_read(&stfb->iface->stamp);
   } while(stfb->iface_stamp != new_stamp);

   width = stfb->Base.Width;
   height = stfb->Base.Height;

   for (i = 0; i < stfb->num_statts; i++) {
      struct st_renderbuffer *strb;
      struct pipe_surface *ps, surf_tmpl;
      gl_buffer_index idx;

      if (!textures[i])
         continue;

      idx = attachment_to_buffer_index(stfb->statts[i]);
      if (idx >= BUFFER_COUNT) {
         pipe_resource_reference(&textures[i], NULL);
         continue;
      }

      strb = st_renderbuffer(stfb->Base.Attachment[idx].Renderbuffer);
      assert(strb);
      if (strb->texture == textures[i]) {
         pipe_resource_reference(&textures[i], NULL);
         continue;
      }

      u_surface_default_template(&surf_tmpl, textures[i],
                                 PIPE_BIND_RENDER_TARGET);
      ps = st->pipe->create_surface(st->pipe, textures[i], &surf_tmpl);
      if (ps) {
         pipe_surface_reference(&strb->surface, ps);
         pipe_resource_reference(&strb->texture, ps->texture);
         /* ownership transfered */
         pipe_surface_reference(&ps, NULL);

         changed = TRUE;

         strb->Base.Width = strb->surface->width;
         strb->Base.Height = strb->surface->height;

         width = strb->Base.Width;
         height = strb->Base.Height;
      }

      pipe_resource_reference(&textures[i], NULL);
   }

   if (changed) {
      ++stfb->stamp;
      _mesa_resize_framebuffer(st->ctx, &stfb->Base, width, height);
   }
}
Пример #15
0
/**
 * gl_renderbuffer::AllocStorage()
 * This is called to allocate the original drawing surface, and
 * during window resize.
 */
static GLboolean
st_renderbuffer_alloc_storage(struct gl_context * ctx,
                              struct gl_renderbuffer *rb,
                              GLenum internalFormat,
                              GLuint width, GLuint height)
{
   struct st_context *st = st_context(ctx);
   struct pipe_context *pipe = st->pipe;
   struct pipe_screen *screen = st->pipe->screen;
   struct st_renderbuffer *strb = st_renderbuffer(rb);
   enum pipe_format format = PIPE_FORMAT_NONE;
   struct pipe_surface surf_tmpl;
   struct pipe_resource templ;

   /* init renderbuffer fields */
   strb->Base.Width  = width;
   strb->Base.Height = height;
   strb->Base._BaseFormat = _mesa_base_fbo_format(ctx, internalFormat);
   strb->defined = GL_FALSE;  /* undefined contents now */

   if (strb->software) {
      return st_renderbuffer_alloc_sw_storage(ctx, rb, internalFormat,
                                              width, height);
   }

   /* Free the old surface and texture
    */
   pipe_surface_reference( &strb->surface, NULL );
   pipe_resource_reference( &strb->texture, NULL );

   /* If an sRGB framebuffer is unsupported, sRGB formats behave like linear
    * formats.
    */
   if (!ctx->Extensions.EXT_framebuffer_sRGB) {
      internalFormat = _mesa_get_linear_internalformat(internalFormat);
   }

   /* Handle multisample renderbuffers first.
    *
    * From ARB_framebuffer_object:
    *   If <samples> is zero, then RENDERBUFFER_SAMPLES is set to zero.
    *   Otherwise <samples> represents a request for a desired minimum
    *   number of samples. Since different implementations may support
    *   different sample counts for multisampled rendering, the actual
    *   number of samples allocated for the renderbuffer image is
    *   implementation dependent.  However, the resulting value for
    *   RENDERBUFFER_SAMPLES is guaranteed to be greater than or equal
    *   to <samples> and no more than the next larger sample count supported
    *   by the implementation.
    *
    * So let's find the supported number of samples closest to NumSamples.
    * (NumSamples == 1) is treated the same as (NumSamples == 0).
    */
   if (rb->NumSamples > 1) {
      unsigned i;

      for (i = rb->NumSamples; i <= ctx->Const.MaxSamples; i++) {
         format = st_choose_renderbuffer_format(st, internalFormat, i);

         if (format != PIPE_FORMAT_NONE) {
            rb->NumSamples = i;
            break;
         }
      }
   } else {
      format = st_choose_renderbuffer_format(st, internalFormat, 0);
   }

   /* Not setting gl_renderbuffer::Format here will cause
    * FRAMEBUFFER_UNSUPPORTED and ValidateFramebuffer will not be called.
    */
   if (format == PIPE_FORMAT_NONE) {
      return GL_TRUE;
   }

   strb->Base.Format = st_pipe_format_to_mesa_format(format);

   if (width == 0 || height == 0) {
      /* if size is zero, nothing to allocate */
      return GL_TRUE;
   }

   /* Setup new texture template.
    */
   memset(&templ, 0, sizeof(templ));
   templ.target = st->internal_target;
   templ.format = format;
   templ.width0 = width;
   templ.height0 = height;
   templ.depth0 = 1;
   templ.array_size = 1;
   templ.nr_samples = rb->NumSamples;
   if (util_format_is_depth_or_stencil(format)) {
      templ.bind = PIPE_BIND_DEPTH_STENCIL;
   }
   else if (strb->Base.Name != 0) {
      /* this is a user-created renderbuffer */
      templ.bind = PIPE_BIND_RENDER_TARGET;
   }
   else {
      /* this is a window-system buffer */
      templ.bind = (PIPE_BIND_DISPLAY_TARGET |
                    PIPE_BIND_RENDER_TARGET);
   }

   strb->texture = screen->resource_create(screen, &templ);

   if (!strb->texture)
      return FALSE;

   u_surface_default_template(&surf_tmpl, strb->texture);
   strb->surface = pipe->create_surface(pipe,
                                        strb->texture,
                                        &surf_tmpl);
   if (strb->surface) {
      assert(strb->surface->texture);
      assert(strb->surface->format);
      assert(strb->surface->width == width);
      assert(strb->surface->height == height);
   }

   return strb->surface != NULL;
}
Пример #16
0
/**
 * Prepare the renderer for image filtering.
 */
VGboolean renderer_filter_begin(struct renderer *renderer,
                                struct pipe_resource *dst,
                                VGboolean y0_top,
                                VGbitfield channel_mask,
                                const struct pipe_sampler_state **samplers,
                                struct pipe_sampler_view **views,
                                VGint num_samplers,
                                void *fs,
                                const void *const_buffer,
                                VGint const_buffer_len)
{
   struct pipe_surface *surf, surf_tmpl;

   assert(renderer->state == RENDERER_STATE_INIT);

   if (!fs)
      return VG_FALSE;
   if (!renderer_can_support(renderer, dst, PIPE_BIND_RENDER_TARGET))
      return VG_FALSE;

   u_surface_default_template(&surf_tmpl, dst);
   surf = renderer->pipe->create_surface(renderer->pipe, dst, &surf_tmpl);
   if (!surf)
      return VG_FALSE;

   cso_save_framebuffer(renderer->cso);
   cso_save_viewport(renderer->cso);
   cso_save_blend(renderer->cso);

   /* set the image as the target */
   renderer_set_target(renderer, surf, NULL, y0_top);
   pipe_surface_reference(&surf, NULL);

   renderer_set_blend(renderer, channel_mask);

   if (num_samplers) {
      struct pipe_resource *tex;

      cso_save_samplers(renderer->cso, PIPE_SHADER_FRAGMENT);
      cso_save_sampler_views(renderer->cso, PIPE_SHADER_FRAGMENT);
      cso_save_fragment_shader(renderer->cso);
      cso_save_vertex_shader(renderer->cso);

      renderer_set_custom_fs(renderer, fs,
                             samplers, views, num_samplers,
                             const_buffer, const_buffer_len);
      renderer_set_vs(renderer, RENDERER_VS_TEXTURE);

      tex = views[0]->texture;
      renderer->u.filter.tex_width = tex->width0;
      renderer->u.filter.tex_height = tex->height0;
      renderer->u.filter.use_sampler = VG_TRUE;
   }
   else {
      cso_save_fragment_shader(renderer->cso);

      renderer_set_custom_fs(renderer, fs, NULL, NULL, 0,
                             const_buffer, const_buffer_len);

      renderer->u.filter.use_sampler = VG_FALSE;
   }

   renderer_set_mvp(renderer, NULL);

   renderer->state = RENDERER_STATE_FILTER;

   return VG_TRUE;
}
Пример #17
0
/**
 * Generate mipmap images.  It's assumed all needed texture memory is
 * already allocated.
 *
 * \param psv  the sampler view to the texture to generate mipmap levels for
 * \param face  which cube face to generate mipmaps for (0 for non-cube maps)
 * \param baseLevel  the first mipmap level to use as a src
 * \param lastLevel  the last mipmap level to generate
 * \param filter  the minification filter used to generate mipmap levels with
 * \param filter  one of PIPE_TEX_FILTER_LINEAR, PIPE_TEX_FILTER_NEAREST
 */
void
util_gen_mipmap(struct gen_mipmap_state *ctx,
                struct pipe_sampler_view *psv,
                uint face, uint baseLevel, uint lastLevel, uint filter)
{
   struct pipe_context *pipe = ctx->pipe;
   struct pipe_screen *screen = pipe->screen;
   struct pipe_framebuffer_state fb;
   struct pipe_resource *pt = psv->texture;
   uint dstLevel;
   uint offset;
   uint type;
   boolean is_depth = util_format_is_depth_or_stencil(psv->format);

   /* The texture object should have room for the levels which we're
    * about to generate.
    */
   assert(lastLevel <= pt->last_level);

   /* If this fails, why are we here? */
   assert(lastLevel > baseLevel);

   assert(filter == PIPE_TEX_FILTER_LINEAR ||
          filter == PIPE_TEX_FILTER_NEAREST);

   type = util_pipe_tex_to_tgsi_tex(pt->target, 1);

   /* check if we can render in the texture's format */
   if (!screen->is_format_supported(screen, psv->format, pt->target,
                                    pt->nr_samples,
                                    is_depth ? PIPE_BIND_DEPTH_STENCIL :
                                               PIPE_BIND_RENDER_TARGET)) {
      /* The caller should check if the format is renderable. */
      assert(0);
      return;
   }

   /* save state (restored below) */
   cso_save_blend(ctx->cso);
   cso_save_depth_stencil_alpha(ctx->cso);
   cso_save_rasterizer(ctx->cso);
   cso_save_sample_mask(ctx->cso);
   cso_save_samplers(ctx->cso, PIPE_SHADER_FRAGMENT);
   cso_save_sampler_views(ctx->cso, PIPE_SHADER_FRAGMENT);
   cso_save_stream_outputs(ctx->cso);
   cso_save_framebuffer(ctx->cso);
   cso_save_fragment_shader(ctx->cso);
   cso_save_vertex_shader(ctx->cso);
   cso_save_geometry_shader(ctx->cso);
   cso_save_viewport(ctx->cso);
   cso_save_vertex_elements(ctx->cso);
   cso_save_aux_vertex_buffer_slot(ctx->cso);
   cso_save_render_condition(ctx->cso);

   /* bind our state */
   cso_set_blend(ctx->cso, is_depth ? &ctx->blend_keep_color :
                                      &ctx->blend_write_color);
   cso_set_depth_stencil_alpha(ctx->cso, is_depth ? &ctx->dsa_write_depth :
                                                    &ctx->dsa_keep_depth);
   cso_set_rasterizer(ctx->cso, &ctx->rasterizer);
   cso_set_sample_mask(ctx->cso, ~0);
   cso_set_vertex_elements(ctx->cso, 2, ctx->velem);
   cso_set_stream_outputs(ctx->cso, 0, NULL, NULL);
   cso_set_render_condition(ctx->cso, NULL, FALSE, 0);

   set_fragment_shader(ctx, type, is_depth);
   set_vertex_shader(ctx);
   cso_set_geometry_shader_handle(ctx->cso, NULL);

   /* init framebuffer state */
   memset(&fb, 0, sizeof(fb));

   /* set min/mag to same filter for faster sw speed */
   ctx->sampler.mag_img_filter = filter;
   ctx->sampler.min_img_filter = filter;

   for (dstLevel = baseLevel + 1; dstLevel <= lastLevel; dstLevel++) {
      const uint srcLevel = dstLevel - 1;
      struct pipe_viewport_state vp;
      unsigned nr_layers, layer, i;
      float rcoord = 0.0f;

      if (pt->target == PIPE_TEXTURE_3D)
         nr_layers = u_minify(pt->depth0, dstLevel);
      else if (pt->target == PIPE_TEXTURE_2D_ARRAY ||
               pt->target == PIPE_TEXTURE_1D_ARRAY ||
               pt->target == PIPE_TEXTURE_CUBE_ARRAY)
	 nr_layers = pt->array_size;
      else
         nr_layers = 1;

      for (i = 0; i < nr_layers; i++) {
         struct pipe_surface *surf, surf_templ;
         if (pt->target == PIPE_TEXTURE_3D) {
            /* in theory with geom shaders and driver with full layer support
               could do that in one go. */
            layer = i;
            /* XXX hmm really? */
            rcoord = (float)layer / (float)nr_layers + 1.0f / (float)(nr_layers * 2);
         } else if (pt->target == PIPE_TEXTURE_2D_ARRAY ||
                    pt->target == PIPE_TEXTURE_1D_ARRAY) {
	    layer = i;
	    rcoord = (float)layer;
         } else if (pt->target == PIPE_TEXTURE_CUBE_ARRAY) {
            layer = i;
            face = layer % 6;
            rcoord = layer / 6;
	 } else
            layer = face;

         u_surface_default_template(&surf_templ, pt);
         surf_templ.u.tex.level = dstLevel;
         surf_templ.u.tex.first_layer = layer;
         surf_templ.u.tex.last_layer = layer;
         surf = pipe->create_surface(pipe, pt, &surf_templ);

         /*
          * Setup framebuffer / dest surface
          */
         if (is_depth) {
            fb.nr_cbufs = 0;
            fb.zsbuf = surf;
         }
         else {
            fb.nr_cbufs = 1;
            fb.cbufs[0] = surf;
         }
         fb.width = u_minify(pt->width0, dstLevel);
         fb.height = u_minify(pt->height0, dstLevel);
         cso_set_framebuffer(ctx->cso, &fb);

         /* viewport */
         vp.scale[0] = 0.5f * fb.width;
         vp.scale[1] = 0.5f * fb.height;
         vp.scale[2] = 1.0f;
         vp.scale[3] = 1.0f;
         vp.translate[0] = 0.5f * fb.width;
         vp.translate[1] = 0.5f * fb.height;
         vp.translate[2] = 0.0f;
         vp.translate[3] = 0.0f;
         cso_set_viewport(ctx->cso, &vp);

         /*
          * Setup sampler state
          * Note: we should only have to set the min/max LOD clamps to ensure
          * we grab texels from the right mipmap level.  But some hardware
          * has trouble with min clamping so we also set the lod_bias to
          * try to work around that.
          */
         ctx->sampler.min_lod = ctx->sampler.max_lod = (float) srcLevel;
         ctx->sampler.lod_bias = (float) srcLevel;
         cso_single_sampler(ctx->cso, PIPE_SHADER_FRAGMENT, 0, &ctx->sampler);
         cso_single_sampler_done(ctx->cso, PIPE_SHADER_FRAGMENT);

         cso_set_sampler_views(ctx->cso, PIPE_SHADER_FRAGMENT, 1, &psv);

         /* quad coords in clip coords */
         offset = set_vertex_data(ctx,
                                  pt->target,
                                  face,
                                  rcoord);

         util_draw_vertex_buffer(ctx->pipe,
                                 ctx->cso,
                                 ctx->vbuf,
                                 cso_get_aux_vertex_buffer_slot(ctx->cso),
                                 offset,
                                 PIPE_PRIM_TRIANGLE_FAN,
                                 4,  /* verts */
                                 2); /* attribs/vert */

         /* need to signal that the texture has changed _after_ rendering to it */
         pipe_surface_reference( &surf, NULL );
      }
   }

   /* restore state we changed */
   cso_restore_blend(ctx->cso);
   cso_restore_depth_stencil_alpha(ctx->cso);
   cso_restore_rasterizer(ctx->cso);
   cso_restore_sample_mask(ctx->cso);
   cso_restore_samplers(ctx->cso, PIPE_SHADER_FRAGMENT);
   cso_restore_sampler_views(ctx->cso, PIPE_SHADER_FRAGMENT);
   cso_restore_framebuffer(ctx->cso);
   cso_restore_fragment_shader(ctx->cso);
   cso_restore_vertex_shader(ctx->cso);
   cso_restore_geometry_shader(ctx->cso);
   cso_restore_viewport(ctx->cso);
   cso_restore_vertex_elements(ctx->cso);
   cso_restore_stream_outputs(ctx->cso);
   cso_restore_aux_vertex_buffer_slot(ctx->cso);
   cso_restore_render_condition(ctx->cso);
}
Пример #18
0
static Bool
ExaPrepareCopy(PixmapPtr pSrcPixmap, PixmapPtr pDstPixmap, int xdir,
	       int ydir, int alu, Pixel planeMask)
{
    ScrnInfoPtr pScrn = xf86Screens[pDstPixmap->drawable.pScreen->myNum];
    modesettingPtr ms = modesettingPTR(pScrn);
    struct exa_context *exa = ms->exa;
    struct exa_pixmap_priv *priv = exaGetPixmapDriverPrivate(pDstPixmap);
    struct exa_pixmap_priv *src_priv = exaGetPixmapDriverPrivate(pSrcPixmap);

    exa_debug_printf("ExaPrepareCopy\n");

    if (!exa->accel)
	return FALSE;

    if (!exa->pipe)
	XORG_FALLBACK("accel not enabled");

    if (!priv || !priv->tex)
	XORG_FALLBACK("pDst %s", !priv ? "!priv" : "!priv->tex");

    if (!src_priv || !src_priv->tex)
	XORG_FALLBACK("pSrc %s", !src_priv ? "!priv" : "!priv->tex");

    if (!EXA_PM_IS_SOLID(&pSrcPixmap->drawable, planeMask))
	XORG_FALLBACK("planeMask is not solid");

    if (alu != GXcopy)
	XORG_FALLBACK("alu not GXcopy");

    if (!exa->scrn->is_format_supported(exa->scrn, priv->tex->format,
                                        priv->tex->target, 0,
                                        PIPE_BIND_RENDER_TARGET))
	XORG_FALLBACK("pDst format %s", util_format_name(priv->tex->format));

    if (!exa->scrn->is_format_supported(exa->scrn, src_priv->tex->format,
                                        src_priv->tex->target, 0,
                                        PIPE_BIND_SAMPLER_VIEW))
	XORG_FALLBACK("pSrc format %s", util_format_name(src_priv->tex->format));

    exa->copy.src = src_priv;
    exa->copy.dst = priv;

    /* XXX this used to use resource_copy_region for same-surface copies,
     * but they were redefined to not allow overlaps (some of the util code
     * always assumed this anyway).
     * Drivers should implement accelerated resource_copy_region or it will
     * be slow - disable for now.
     */
    if (0 && exa->copy.src != exa->copy.dst) {
       exa->copy.use_surface_copy = TRUE;
    }
    else {
       struct pipe_surface surf_tmpl;
       exa->copy.use_surface_copy = FALSE;

       if (exa->copy.dst == exa->copy.src)
          exa->copy.src_texture = renderer_clone_texture( exa->renderer,
                                                          exa->copy.src->tex );
       else
          pipe_resource_reference(&exa->copy.src_texture,
                                 exa->copy.src->tex);

       memset(&surf_tmpl, 0, sizeof(surf_tmpl));
       u_surface_default_template(&surf_tmpl, exa->copy.dst->tex,
                                  PIPE_BIND_RENDER_TARGET);
       exa->copy.dst_surface =
          exa->pipe->create_surface(exa->pipe,
                                    exa->copy.dst->tex,
                                    &surf_tmpl);


       renderer_copy_prepare(exa->renderer, 
                             exa->copy.dst_surface,
                             exa->copy.src_texture );
    }


    return TRUE;
}