Example #1
0
static struct native_surface *
dri2_display_create_pixmap_surface(struct native_display *ndpy,
                                   EGLNativePixmapType pix,
                                   const struct native_config *nconf)
{
   struct dri2_surface *dri2surf;

   if (!nconf) {
      struct dri2_display *dri2dpy = dri2_display(ndpy);
      uint depth, nconf_depth;
      int i;

      depth = x11_drawable_get_depth(dri2dpy->xscr, (Drawable) pix);
      for (i = 0; i < dri2dpy->num_configs; i++) {
         nconf_depth = util_format_get_blocksizebits(
               dri2dpy->configs[i].base.color_format);
         /* simple depth match for now */
         if (depth == nconf_depth ||
             (depth == 24 && depth + 8 == nconf_depth)) {
            nconf = &dri2dpy->configs[i].base;
            break;
         }
      }

      if (!nconf)
         return NULL;
   }

   dri2surf = dri2_display_create_surface(ndpy,
         (Drawable) pix, nconf->color_format);
   return (dri2surf) ? &dri2surf->base : NULL;
}
enum a4xx_tex_fetchsize
fd4_pipe2fetchsize(enum pipe_format format)
{
	switch (util_format_get_blocksizebits(format)) {
	case 8:   return TFETCH4_1_BYTE;
	case 16:  return TFETCH4_2_BYTE;
	case 32:  return TFETCH4_4_BYTE;
	case 64:  return TFETCH4_8_BYTE;
	case 128: return TFETCH4_16_BYTE;
	default:
		debug_printf("Unknown block size for format %s: %d\n",
				util_format_name(format),
				util_format_get_blocksizebits(format));
		return TFETCH4_1_BYTE;
	}
}
Example #3
0
static boolean
nv50_screen_is_format_supported(struct pipe_screen *pscreen,
                                enum pipe_format format,
                                enum pipe_texture_target target,
                                unsigned sample_count,
                                unsigned bindings)
{
   if (sample_count > 8)
      return FALSE;
   if (!(0x117 & (1 << sample_count))) /* 0, 1, 2, 4 or 8 */
      return FALSE;
   if (sample_count == 8 && util_format_get_blocksizebits(format) >= 128)
      return FALSE;

   if (!util_format_is_supported(format, bindings))
      return FALSE;

   switch (format) {
   case PIPE_FORMAT_Z16_UNORM:
      if (nv50_screen(pscreen)->tesla->oclass < NVA0_3D_CLASS)
         return FALSE;
      break;
   default:
      break;
   }

   /* transfers & shared are always supported */
   bindings &= ~(PIPE_BIND_TRANSFER_READ |
                 PIPE_BIND_TRANSFER_WRITE |
                 PIPE_BIND_SHARED);

   return (nv50_format_table[format].usage & bindings) == bindings;
}
Example #4
0
static boolean
nvc0_screen_is_format_supported(struct pipe_screen *pscreen,
                                enum pipe_format format,
                                enum pipe_texture_target target,
                                unsigned sample_count,
                                unsigned bindings)
{
   if (sample_count > 8)
      return false;
   if (!(0x117 & (1 << sample_count))) /* 0, 1, 2, 4 or 8 */
      return false;

   if (!util_format_is_supported(format, bindings))
      return false;

   if ((bindings & PIPE_BIND_SAMPLER_VIEW) && (target != PIPE_BUFFER))
      if (util_format_get_blocksizebits(format) == 3 * 32)
         return false;

   /* transfers & shared are always supported */
   bindings &= ~(PIPE_BIND_TRANSFER_READ |
                 PIPE_BIND_TRANSFER_WRITE |
                 PIPE_BIND_SHARED);

   return (nvc0_format_table[format].usage & bindings) == bindings;
}
Example #5
0
static bool can_fast_clear_color(struct pipe_context *ctx)
{
	struct r600_context *rctx = (struct r600_context *)ctx;
	struct pipe_framebuffer_state *fb = &rctx->framebuffer.state;
	int i;

	if (rctx->b.chip_class < EVERGREEN) {
		return false;
	}

	for (i = 0; i < fb->nr_cbufs; i++) {
		struct r600_texture *tex = (struct r600_texture *)fb->cbufs[i]->texture;

		if (tex->cmask_size == 0) {
			return false;
		}

		/* 128-bit formats are unuspported */
		if (util_format_get_blocksizebits(fb->cbufs[i]->format) > 64) {
			return false;
		}

		/* the clear is allowed if all layers are bound */
		if (fb->cbufs[i]->u.tex.first_layer != 0 ||
		    fb->cbufs[i]->u.tex.last_layer != util_max_layer(&tex->resource.b.b, 0)) {
			return false;
		}
	}

	return true;
}
Example #6
0
/**
 * Add textures as DRM framebuffers.
 */
static boolean
drm_surface_init_framebuffers(struct native_surface *nsurf, boolean need_back)
{
   struct drm_surface *drmsurf = drm_surface(nsurf);
   struct drm_display *drmdpy = drmsurf->drmdpy;
   int num_framebuffers = (need_back) ? 2 : 1;
   int i, err;

   for (i = 0; i < num_framebuffers; i++) {
      struct drm_framebuffer *fb;
      enum native_attachment natt;
      struct winsys_handle whandle;
      uint block_bits;

      if (i == 0) {
         fb = &drmsurf->front_fb;
         natt = NATIVE_ATTACHMENT_FRONT_LEFT;
      }
      else {
         fb = &drmsurf->back_fb;
         natt = NATIVE_ATTACHMENT_BACK_LEFT;
      }

      if (!fb->texture) {
         /* make sure the texture has been allocated */
         resource_surface_add_resources(drmsurf->rsurf, 1 << natt);
         fb->texture =
            resource_surface_get_single_resource(drmsurf->rsurf, natt);
         if (!fb->texture)
            return FALSE;
      }

      /* already initialized */
      if (fb->buffer_id)
         continue;

      /* TODO detect the real value */
      fb->is_passive = TRUE;

      memset(&whandle, 0, sizeof(whandle));
      whandle.type = DRM_API_HANDLE_TYPE_KMS;

      if (!drmdpy->base.screen->resource_get_handle(drmdpy->base.screen,
               fb->texture, &whandle))
         return FALSE;

      block_bits = util_format_get_blocksizebits(drmsurf->color_format);
      err = drmModeAddFB(drmdpy->fd, drmsurf->width, drmsurf->height,
            block_bits, block_bits, whandle.stride, whandle.handle,
            &fb->buffer_id);
      if (err) {
         fb->buffer_id = 0;
         return FALSE;
      }
   }

   return TRUE;
}
Example #7
0
static boolean
nvc0_screen_is_format_supported(struct pipe_screen *pscreen,
                                enum pipe_format format,
                                enum pipe_texture_target target,
                                unsigned sample_count,
                                unsigned bindings)
{
   const struct util_format_description *desc = util_format_description(format);

   if (sample_count > 8)
      return false;
   if (!(0x117 & (1 << sample_count))) /* 0, 1, 2, 4 or 8 */
      return false;

   /* Short-circuit the rest of the logic -- this is used by the state tracker
    * to determine valid MS levels in a no-attachments scenario.
    */
   if (format == PIPE_FORMAT_NONE && bindings & PIPE_BIND_RENDER_TARGET)
      return true;

   if (!util_format_is_supported(format, bindings))
      return false;

   if ((bindings & PIPE_BIND_SAMPLER_VIEW) && (target != PIPE_BUFFER))
      if (util_format_get_blocksizebits(format) == 3 * 32)
         return false;

   if (bindings & PIPE_BIND_LINEAR)
      if (util_format_is_depth_or_stencil(format) ||
          (target != PIPE_TEXTURE_1D &&
           target != PIPE_TEXTURE_2D &&
           target != PIPE_TEXTURE_RECT) ||
          sample_count > 1)
         return false;

   /* Restrict ETC2 and ASTC formats here. These are only supported on GK20A.
    */
   if ((desc->layout == UTIL_FORMAT_LAYOUT_ETC ||
        desc->layout == UTIL_FORMAT_LAYOUT_ASTC) &&
       /* The claim is that this should work on GM107 but it doesn't. Need to
        * test further and figure out if it's a nouveau issue or a HW one.
       nouveau_screen(pscreen)->class_3d < GM107_3D_CLASS &&
        */
       nouveau_screen(pscreen)->class_3d != NVEA_3D_CLASS)
      return false;

   /* transfers & shared are always supported */
   bindings &= ~(PIPE_BIND_TRANSFER_READ |
                 PIPE_BIND_TRANSFER_WRITE |
                 PIPE_BIND_LINEAR |
                 PIPE_BIND_SHARED);

   return (( nvc0_format_table[format].usage |
            nvc0_vertex_format[format].usage) & bindings) == bindings;
}
Example #8
0
enum a3xx_tex_fetchsize
fd3_pipe2fetchsize(enum pipe_format format)
{
	if (format == PIPE_FORMAT_Z32_FLOAT_S8X24_UINT)
		format = PIPE_FORMAT_Z32_FLOAT;
	else if (util_format_description(format)->layout == UTIL_FORMAT_LAYOUT_RGTC)
		format = PIPE_FORMAT_R8G8B8A8_UNORM;
	switch (util_format_get_blocksizebits(format) / util_format_get_blockwidth(format)) {
	case 8: return TFETCH_1_BYTE;
	case 16: return TFETCH_2_BYTE;
	case 32: return TFETCH_4_BYTE;
	case 64: return TFETCH_8_BYTE;
	case 128: return TFETCH_16_BYTE;
	default:
		debug_printf("Unknown block size for format %s: %d\n",
					 util_format_name(format),
					 util_format_get_blocksizebits(format));
		return TFETCH_DISABLE;
	}
}
Example #9
0
static uint32_t r300_depth_clear_cb_value(enum pipe_format format,
                                          const float* rgba)
{
    union util_color uc;
    util_pack_color(rgba, format, &uc);

    if (util_format_get_blocksizebits(format) == 32)
        return uc.ui;
    else
        return uc.us | (uc.us << 16);
}
Example #10
0
static struct sw_displaytarget *
gdi_sw_displaytarget_create(struct sw_winsys *winsys,
                                  unsigned tex_usage,
                                  enum pipe_format format,
                                  unsigned width, unsigned height,
                                  unsigned alignment,
                                  const void *front_private,
                                  unsigned *stride)
{
   struct gdi_sw_displaytarget *gdt;
   unsigned cpp;
   unsigned bpp;
   
   gdt = CALLOC_STRUCT(gdi_sw_displaytarget);
   if(!gdt)
      goto no_gdt;

   gdt->format = format;
   gdt->width = width;
   gdt->height = height;

   bpp = util_format_get_blocksizebits(format);
   cpp = util_format_get_blocksize(format);
   
   gdt->stride = align(width * cpp, alignment);
   gdt->size = gdt->stride * height;
   
   gdt->data = align_malloc(gdt->size, alignment);
   if(!gdt->data)
      goto no_data;

   gdt->bmi.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
   gdt->bmi.bmiHeader.biWidth = gdt->stride / cpp;
   gdt->bmi.bmiHeader.biHeight= -(long)height;
   gdt->bmi.bmiHeader.biPlanes = 1;
   gdt->bmi.bmiHeader.biBitCount = bpp;
   gdt->bmi.bmiHeader.biCompression = BI_RGB;
   gdt->bmi.bmiHeader.biSizeImage = 0;
   gdt->bmi.bmiHeader.biXPelsPerMeter = 0;
   gdt->bmi.bmiHeader.biYPelsPerMeter = 0;
   gdt->bmi.bmiHeader.biClrUsed = 0;
   gdt->bmi.bmiHeader.biClrImportant = 0;

   *stride = gdt->stride;
   return (struct sw_displaytarget *)gdt;

no_data:
   FREE(gdt);
no_gdt:
   return NULL;
}
Example #11
0
enum a4xx_tex_fetchsize
fd4_pipe2fetchsize(enum pipe_format format)
{
	if (format == PIPE_FORMAT_Z32_FLOAT_S8X24_UINT)
		format = PIPE_FORMAT_Z32_FLOAT;

	if (util_format_description(format)->layout == UTIL_FORMAT_LAYOUT_ASTC)
		return TFETCH4_16_BYTE;

	switch (util_format_get_blocksizebits(format) / util_format_get_blockwidth(format)) {
	case 8:   return TFETCH4_1_BYTE;
	case 16:  return TFETCH4_2_BYTE;
	case 32:  return TFETCH4_4_BYTE;
	case 64:  return TFETCH4_8_BYTE;
	case 96:  return TFETCH4_1_BYTE; /* Does this matter? */
	case 128: return TFETCH4_16_BYTE;
	default:
		debug_printf("Unknown block size for format %s: %d\n",
				util_format_name(format),
				util_format_get_blocksizebits(format));
		return TFETCH4_1_BYTE;
	}
}
Example #12
0
static boolean
nv50_screen_is_format_supported(struct pipe_screen *pscreen,
                                enum pipe_format format,
                                enum pipe_texture_target target,
                                unsigned sample_count,
                                unsigned bindings)
{
   if (sample_count > 8)
      return false;
   if (!(0x117 & (1 << sample_count))) /* 0, 1, 2, 4 or 8 */
      return false;
   if (sample_count == 8 && util_format_get_blocksizebits(format) >= 128)
      return false;

   if (!util_format_is_supported(format, bindings))
      return false;

   switch (format) {
   case PIPE_FORMAT_Z16_UNORM:
      if (nv50_screen(pscreen)->tesla->oclass < NVA0_3D_CLASS)
         return false;
      break;
   default:
      break;
   }

   if (bindings & PIPE_BIND_LINEAR)
      if (util_format_is_depth_or_stencil(format) ||
          (target != PIPE_TEXTURE_1D &&
           target != PIPE_TEXTURE_2D &&
           target != PIPE_TEXTURE_RECT) ||
          sample_count > 1)
         return false;

   /* transfers & shared are always supported */
   bindings &= ~(PIPE_BIND_TRANSFER_READ |
                 PIPE_BIND_TRANSFER_WRITE |
                 PIPE_BIND_LINEAR |
                 PIPE_BIND_SHARED);

   return (( nv50_format_table[format].usage |
            nv50_vertex_format[format].usage) & bindings) == bindings;
}
Example #13
0
static void r300_setup_cbzb_flags(struct r300_screen *rscreen,
                                  struct r300_resource *tex)
{
    unsigned i, bpp;
    boolean first_level_valid;

    bpp = util_format_get_blocksizebits(tex->b.b.b.format);

    /* 1) The texture must be point-sampled,
     * 2) The depth must be 16 or 32 bits.
     * 3) If the midpoint ZB offset is not aligned to 2048, it returns garbage
     *    with certain texture sizes. Macrotiling ensures the alignment. */
    first_level_valid = tex->b.b.b.nr_samples <= 1 &&
                       (bpp == 16 || bpp == 32) &&
                       tex->tex.macrotile[0];

    if (SCREEN_DBG_ON(rscreen, DBG_NO_CBZB))
        first_level_valid = FALSE;

    for (i = 0; i <= tex->b.b.b.last_level; i++)
        tex->tex.cbzb_allowed[i] = first_level_valid && tex->tex.macrotile[i];
}
static struct sw_displaytarget *
kos_sw_displaytarget_create(struct sw_winsys *winsys,
                                  unsigned tex_usage,
                                  enum pipe_format format,
                                  unsigned width, unsigned height,
                                  unsigned alignment,
                                  unsigned *stride)
{
   struct kos_sw_displaytarget *gdt;
   unsigned cpp;
   unsigned bpp;

   gdt = CALLOC_STRUCT(kos_sw_displaytarget);
   if(!gdt)
      goto no_gdt;

   gdt->format = format;
   gdt->width = width;
   gdt->height = height;

   bpp = util_format_get_blocksizebits(format);
   cpp = util_format_get_blocksize(format);

   gdt->stride = align(width * cpp, alignment);
   gdt->size = gdt->stride * height;

   gdt->data = user_alloc(gdt->size);
   if(!gdt->data)
      goto no_data;

   *stride = gdt->stride;
   return (struct sw_displaytarget *)gdt;

no_data:
   FREE(gdt);
no_gdt:
   return NULL;
}
Example #15
0
static void
nvc0_resource_copy_region(struct pipe_context *pipe,
                          struct pipe_resource *dst, unsigned dst_level,
                          unsigned dstx, unsigned dsty, unsigned dstz,
                          struct pipe_resource *src, unsigned src_level,
                          const struct pipe_box *src_box)
{
   struct nvc0_context *nvc0 = nvc0_context(pipe);
   int ret;
   boolean m2mf;
   unsigned dst_layer = dstz, src_layer = src_box->z;

   if (dst->target == PIPE_BUFFER && src->target == PIPE_BUFFER) {
      nouveau_copy_buffer(&nvc0->base,
                          nv04_resource(dst), dstx,
                          nv04_resource(src), src_box->x, src_box->width);
      NOUVEAU_DRV_STAT(&nvc0->screen->base, buf_copy_bytes, src_box->width);
      return;
   }
   NOUVEAU_DRV_STAT(&nvc0->screen->base, tex_copy_count, 1);

   /* 0 and 1 are equal, only supporting 0/1, 2, 4 and 8 */
   assert((src->nr_samples | 1) == (dst->nr_samples | 1));

   m2mf = (src->format == dst->format) ||
      (util_format_get_blocksizebits(src->format) ==
       util_format_get_blocksizebits(dst->format));

   nv04_resource(dst)->status |= NOUVEAU_BUFFER_STATUS_GPU_WRITING;

   if (m2mf) {
      struct nv50_m2mf_rect drect, srect;
      unsigned i;
      unsigned nx = util_format_get_nblocksx(src->format, src_box->width);
      unsigned ny = util_format_get_nblocksy(src->format, src_box->height);

      nv50_m2mf_rect_setup(&drect, dst, dst_level, dstx, dsty, dstz);
      nv50_m2mf_rect_setup(&srect, src, src_level,
                           src_box->x, src_box->y, src_box->z);

      for (i = 0; i < src_box->depth; ++i) {
         nvc0->m2mf_copy_rect(nvc0, &drect, &srect, nx, ny);

         if (nv50_miptree(dst)->layout_3d)
            drect.z++;
         else
            drect.base += nv50_miptree(dst)->layer_stride;

         if (nv50_miptree(src)->layout_3d)
            srect.z++;
         else
            srect.base += nv50_miptree(src)->layer_stride;
      }
      return;
   }

   assert(nv50_2d_dst_format_faithful(dst->format));
   assert(nv50_2d_src_format_faithful(src->format));

   BCTX_REFN(nvc0->bufctx, 2D, nv04_resource(src), RD);
   BCTX_REFN(nvc0->bufctx, 2D, nv04_resource(dst), WR);
   nouveau_pushbuf_bufctx(nvc0->base.pushbuf, nvc0->bufctx);
   nouveau_pushbuf_validate(nvc0->base.pushbuf);

   for (; dst_layer < dstz + src_box->depth; ++dst_layer, ++src_layer) {
      ret = nvc0_2d_texture_do_copy(nvc0->base.pushbuf,
                                    nv50_miptree(dst), dst_level,
                                    dstx, dsty, dst_layer,
                                    nv50_miptree(src), src_level,
                                    src_box->x, src_box->y, src_layer,
                                    src_box->width, src_box->height);
      if (ret)
         break;
   }
   nouveau_bufctx_reset(nvc0->bufctx, 0);
}
Example #16
0
static void
nv50_resource_copy_region(struct pipe_context *pipe,
                          struct pipe_resource *dst, unsigned dst_level,
                          unsigned dstx, unsigned dsty, unsigned dstz,
                          struct pipe_resource *src, unsigned src_level,
                          const struct pipe_box *src_box)
{
   struct nv50_screen *screen = nv50_context(pipe)->screen;
   int ret;
   boolean m2mf;
   unsigned dst_layer = dstz, src_layer = src_box->z;

   /* Fallback for buffers. */
   if (dst->target == PIPE_BUFFER && src->target == PIPE_BUFFER) {
      util_resource_copy_region(pipe, dst, dst_level, dstx, dsty, dstz,
                                src, src_level, src_box);
      return;
   }

   assert(src->nr_samples == dst->nr_samples);

   m2mf = (src->format == dst->format) ||
      (util_format_get_blocksizebits(src->format) ==
       util_format_get_blocksizebits(dst->format));

   nv04_resource(dst)->status |= NOUVEAU_BUFFER_STATUS_GPU_WRITING;

   if (m2mf) {
      struct nv50_m2mf_rect drect, srect;
      unsigned i;
      unsigned nx = util_format_get_nblocksx(src->format, src_box->width);
      unsigned ny = util_format_get_nblocksy(src->format, src_box->height);

      nv50_m2mf_rect_setup(&drect, dst, dst_level, dstx, dsty, dstz);
      nv50_m2mf_rect_setup(&srect, src, src_level,
                           src_box->x, src_box->y, src_box->z);

      for (i = 0; i < src_box->depth; ++i) {
         nv50_m2mf_transfer_rect(&screen->base.base, &drect, &srect, nx, ny);

         if (nv50_miptree(dst)->layout_3d)
            drect.z++;
         else
            drect.base += nv50_miptree(dst)->layer_stride;

         if (nv50_miptree(src)->layout_3d)
            srect.z++;
         else
            srect.base += nv50_miptree(src)->layer_stride;
      }
      return;
   }

   assert((src->format == dst->format) ||
          (nv50_2d_format_faithful(src->format) &&
           nv50_2d_format_faithful(dst->format)));

   for (; dst_layer < dstz + src_box->depth; ++dst_layer, ++src_layer) {
      ret = nv50_2d_texture_do_copy(screen->base.channel,
                                    nv50_miptree(dst), dst_level,
                                    dstx, dsty, dst_layer,
                                    nv50_miptree(src), src_level,
                                    src_box->x, src_box->y, src_layer,
                                    src_box->width, src_box->height);
      if (ret)
         return;
   }
}
void evergreen_do_fast_color_clear(struct r600_common_context *rctx,
				   struct pipe_framebuffer_state *fb,
				   struct r600_atom *fb_state,
				   unsigned *buffers,
				   const union pipe_color_union *color)
{
	int i;

	if (rctx->current_render_cond)
		return;

	for (i = 0; i < fb->nr_cbufs; i++) {
		struct r600_texture *tex;
		unsigned clear_bit = PIPE_CLEAR_COLOR0 << i;

		if (!fb->cbufs[i])
			continue;

		/* if this colorbuffer is not being cleared */
		if (!(*buffers & clear_bit))
			continue;

		tex = (struct r600_texture *)fb->cbufs[i]->texture;

		/* 128-bit formats are unusupported */
		if (util_format_get_blocksizebits(fb->cbufs[i]->format) > 64) {
			continue;
		}

		/* the clear is allowed if all layers are bound */
		if (fb->cbufs[i]->u.tex.first_layer != 0 ||
		    fb->cbufs[i]->u.tex.last_layer != util_max_layer(&tex->resource.b.b, 0)) {
			continue;
		}

		/* cannot clear mipmapped textures */
		if (fb->cbufs[i]->texture->last_level != 0) {
			continue;
		}

		/* only supported on tiled surfaces */
		if (tex->surface.level[0].mode < RADEON_SURF_MODE_1D) {
			continue;
		}

		/* fast color clear with 1D tiling doesn't work on old kernels and CIK */
		if (tex->surface.level[0].mode == RADEON_SURF_MODE_1D &&
		    rctx->chip_class >= CIK &&
		    rctx->screen->info.drm_major == 2 &&
		    rctx->screen->info.drm_minor < 38) {
			continue;
		}

		/* ensure CMASK is enabled */
		r600_texture_alloc_cmask_separate(rctx->screen, tex);
		if (tex->cmask.size == 0) {
			continue;
		}

		/* Do the fast clear. */
		evergreen_set_clear_color(tex, fb->cbufs[i]->format, color);
		rctx->clear_buffer(&rctx->b, &tex->cmask_buffer->b.b,
				   tex->cmask.offset, tex->cmask.size, 0, true);

		tex->dirty_level_mask |= 1 << fb->cbufs[i]->u.tex.level;
		rctx->set_atom_dirty(rctx, fb_state, true);
		*buffers &= ~clear_bit;
	}
}
Example #18
0
void
nve4_set_surface_info(struct nouveau_pushbuf *push,
                      struct pipe_surface *psf,
                      struct nvc0_screen *screen)
{
   struct nv50_surface *sf = nv50_surface(psf);
   struct nv04_resource *res;
   uint64_t address;
   uint32_t *const info = push->cur;
   uint8_t log2cpp;

   if (psf && !nve4_su_format_map[psf->format])
      NOUVEAU_ERR("unsupported surface format, try is_format_supported() !\n");

   push->cur += 16;

   if (!psf || !nve4_su_format_map[psf->format]) {
      memset(info, 0, 16 * sizeof(*info));

      info[0] = 0xbadf0000;
      info[1] = 0x80004000;
      info[12] = nve4_suldp_lib_offset[PIPE_FORMAT_R32G32B32A32_UINT] +
         screen->lib_code->start;
      return;
   }
   res = nv04_resource(sf->base.texture);

   address = res->address + sf->offset;

   info[8] = sf->width;
   info[9] = sf->height;
   info[10] = sf->depth;
   switch (res->base.target) {
   case PIPE_TEXTURE_1D_ARRAY:
      info[11] = 1;
      break;
   case PIPE_TEXTURE_2D:
   case PIPE_TEXTURE_RECT:
      info[11] = 2;
      break;
   case PIPE_TEXTURE_3D:
      info[11] = 3;
      break;
   case PIPE_TEXTURE_2D_ARRAY:
   case PIPE_TEXTURE_CUBE:
   case PIPE_TEXTURE_CUBE_ARRAY:
      info[11] = 4;
      break;
   default:
      info[11] = 0;
      break;
   }
   log2cpp = (0xf000 & nve4_su_format_aux_map[sf->base.format]) >> 12;

   info[12] = nve4_suldp_lib_offset[sf->base.format] + screen->lib_code->start;

   /* limit in bytes for raw access */
   info[13] = (0x06 << 22) | ((sf->width << log2cpp) - 1);

   info[1] = nve4_su_format_map[sf->base.format];

#if 0
   switch (util_format_get_blocksizebits(sf->base.format)) {
   case  16: info[1] |= 1 << 16; break;
   case  32: info[1] |= 2 << 16; break;
   case  64: info[1] |= 3 << 16; break;
   case 128: info[1] |= 4 << 16; break;
   default:
      break;
   }
#else
   info[1] |= log2cpp << 16;
   info[1] |=  0x4000;
   info[1] |= (0x0f00 & nve4_su_format_aux_map[sf->base.format]);
#endif

   if (res->base.target == PIPE_BUFFER) {
      info[0]  = address >> 8;
      info[2]  = sf->width - 1;
      info[2] |= (0xff & nve4_su_format_aux_map[sf->base.format]) << 22;
      info[3]  = 0;
      info[4]  = 0;
      info[5]  = 0;
      info[6]  = 0;
      info[7]  = 0;
      info[14] = 0;
      info[15] = 0;
   } else {
Example #19
0
static void r300_setup_hyperz_properties(struct r300_screen *screen,
                                         struct r300_resource *tex)
{
    /* The tile size of 1 DWORD in ZMASK RAM is:
     *
     * GPU    Pipes    4x4 mode   8x8 mode
     * ------------------------------------------
     * R580   4P/1Z    32x32      64x64
     * RV570  3P/1Z    48x16      96x32
     * RV530  1P/2Z    32x16      64x32
     *        1P/1Z    16x16      32x32
     */
    static unsigned zmask_blocks_x_per_dw[4] = {4, 8, 12, 8};
    static unsigned zmask_blocks_y_per_dw[4] = {4, 4,  4, 8};

    /* In HIZ RAM, one dword is always 8x8 pixels (each byte is 4x4 pixels),
     * but the blocks have very weird ordering.
     *
     * With 2 pipes and an image of size 8xY, where Y >= 1,
     * clearing 4 dwords clears blocks like this:
     *
     *    01012323
     *
     * where numbers correspond to dword indices. The blocks are interleaved
     * in the X direction, so the alignment must be 4x1 blocks (32x8 pixels).
     *
     * With 4 pipes and an image of size 8xY, where Y >= 4,
     * clearing 8 dwords clears blocks like this:
     *    01012323
     *    45456767
     *    01012323
     *    45456767
     * where numbers correspond to dword indices. The blocks are interleaved
     * in both directions, so the alignment must be 4x4 blocks (32x32 pixels)
     */
    static unsigned hiz_align_x[4] = {8, 32, 48, 32};
    static unsigned hiz_align_y[4] = {8, 8, 8, 32};

    if (util_format_is_depth_or_stencil(tex->b.b.b.format) &&
        util_format_get_blocksizebits(tex->b.b.b.format) == 32 &&
        tex->tex.microtile) {
        unsigned i, pipes;

        if (screen->caps.family == CHIP_FAMILY_RV530) {
            pipes = screen->info.r300_num_z_pipes;
        } else {
            pipes = screen->info.r300_num_gb_pipes;
        }

        for (i = 0; i <= tex->b.b.b.last_level; i++) {
            unsigned zcomp_numdw, zcompsize, hiz_numdw, stride, height;

            stride = align(tex->tex.stride_in_pixels[i], 16);
            height = u_minify(tex->b.b.b.height0, i);

            /* The 8x8 compression mode needs macrotiling. */
            zcompsize = screen->caps.z_compress == R300_ZCOMP_8X8 &&
                       tex->tex.macrotile[i] &&
                       tex->b.b.b.nr_samples <= 1 ? 8 : 4;

            /* Get the ZMASK buffer size in dwords. */
            zcomp_numdw = r300_pixels_to_dwords(stride, height,
                                zmask_blocks_x_per_dw[pipes-1] * zcompsize,
                                zmask_blocks_y_per_dw[pipes-1] * zcompsize);

            /* Check whether we have enough ZMASK memory. */
            if (util_format_get_blocksizebits(tex->b.b.b.format) == 32 &&
                zcomp_numdw <= screen->caps.zmask_ram * pipes) {
                tex->tex.zmask_dwords[i] = zcomp_numdw;
                tex->tex.zcomp8x8[i] = zcompsize == 8;

                tex->tex.zmask_stride_in_pixels[i] =
                    util_align_npot(stride, zmask_blocks_x_per_dw[pipes-1] * zcompsize);
            } else {
                tex->tex.zmask_dwords[i] = 0;
                tex->tex.zcomp8x8[i] = FALSE;
                tex->tex.zmask_stride_in_pixels[i] = 0;
            }

            /* Now setup HIZ. */
            stride = util_align_npot(stride, hiz_align_x[pipes-1]);
            height = align(height, hiz_align_y[pipes-1]);

            /* Get the HIZ buffer size in dwords. */
            hiz_numdw = (stride * height) / (8*8 * pipes);

            /* Check whether we have enough HIZ memory. */
            if (hiz_numdw <= screen->caps.hiz_ram * pipes) {
                tex->tex.hiz_dwords[i] = hiz_numdw;
                tex->tex.hiz_stride_in_pixels[i] = stride;
            } else {
                tex->tex.hiz_dwords[i] = 0;
                tex->tex.hiz_stride_in_pixels[i] = 0;
            }
        }
    }
}
Example #20
0
/* Not required to implement u_resource_vtbl, consider moving to another file:
 */
struct pipe_surface* r300_get_tex_surface(struct pipe_screen* screen,
                                          struct pipe_resource* texture,
					  unsigned face,
					  unsigned level,
					  unsigned zslice,
					  unsigned flags)
{
    struct r300_texture* tex = r300_texture(texture);
    struct r300_surface* surface = CALLOC_STRUCT(r300_surface);

    if (surface) {
        uint32_t offset, tile_height;

        pipe_reference_init(&surface->base.reference, 1);
        pipe_resource_reference(&surface->base.texture, texture);
        surface->base.format = texture->format;
        surface->base.width = u_minify(texture->width0, level);
        surface->base.height = u_minify(texture->height0, level);
        surface->base.usage = flags;
        surface->base.zslice = zslice;
        surface->base.face = face;
        surface->base.level = level;

        surface->buffer = tex->buffer;

        /* Prefer VRAM if there are multiple domains to choose from. */
        surface->domain = tex->domain;
        if (surface->domain & R300_DOMAIN_VRAM)
            surface->domain &= ~R300_DOMAIN_GTT;

        surface->offset = r300_texture_get_offset(&tex->desc,
                                                  level, zslice, face);
        surface->pitch = tex->fb_state.pitch[level];
        surface->format = tex->fb_state.format;

        /* Parameters for the CBZB clear. */
        surface->cbzb_allowed = tex->desc.cbzb_allowed[level];
        surface->cbzb_width = align(surface->base.width, 64);

        /* Height must be aligned to the size of a tile. */
        tile_height = r300_get_pixel_alignment(tex->desc.b.b.format,
                                               tex->desc.b.b.nr_samples,
                                               tex->desc.microtile,
                                               tex->desc.macrotile[level],
                                               DIM_HEIGHT, 0);

        surface->cbzb_height = align((surface->base.height + 1) / 2,
                                     tile_height);

        /* Offset must be aligned to 2K and must point at the beginning
         * of a scanline. */
        offset = surface->offset +
                 tex->desc.stride_in_bytes[level] * surface->cbzb_height;
        surface->cbzb_midpoint_offset = offset & ~2047;

        surface->cbzb_pitch = surface->pitch & 0x1ffffc;

        if (util_format_get_blocksizebits(surface->base.format) == 32)
            surface->cbzb_format = R300_DEPTHFORMAT_24BIT_INT_Z_8BIT_STENCIL;
        else
            surface->cbzb_format = R300_DEPTHFORMAT_16BIT_INT_Z;

        SCREEN_DBG(r300_screen(screen), DBG_CBZB,
                   "CBZB Allowed: %s, Dim: %ix%i, Misalignment: %i, Micro: %s, Macro: %s\n",
                   surface->cbzb_allowed ? "YES" : " NO",
                   surface->cbzb_width, surface->cbzb_height,
                   offset & 2047,
                   tex->desc.microtile ? "YES" : " NO",
                   tex->desc.macrotile[level] ? "YES" : " NO");
    }

    return &surface->base;
}
Example #21
0
static struct pipe_texture *
nv50_miptree_create(struct pipe_screen *pscreen, const struct pipe_texture *tmp)
{
	struct nouveau_device *dev = nouveau_screen(pscreen)->device;
	struct nv50_miptree *mt = CALLOC_STRUCT(nv50_miptree);
	struct pipe_texture *pt = &mt->base.base;
	unsigned width = tmp->width0, height = tmp->height0;
	unsigned depth = tmp->depth0, image_alignment;
	uint32_t tile_flags;
	int ret, i, l;

	*pt = *tmp;
	pipe_reference_init(&pt->reference, 1);
	pt->screen = pscreen;

	switch (pt->format) {
	case PIPE_FORMAT_Z32_FLOAT:
		tile_flags = 0x4800;
		break;
	case PIPE_FORMAT_S8Z24_UNORM:
		tile_flags = 0x1800;
		break;
	case PIPE_FORMAT_Z16_UNORM:
		tile_flags = 0x6c00;
		break;
	case PIPE_FORMAT_Z24X8_UNORM:
	case PIPE_FORMAT_Z24S8_UNORM:
		tile_flags = 0x2800;
		break;
	case PIPE_FORMAT_R32G32B32A32_FLOAT:
	case PIPE_FORMAT_R32G32B32_FLOAT:
		tile_flags = 0x7400;
		break;
	default:
		if ((pt->tex_usage & PIPE_TEXTURE_USAGE_PRIMARY) &&
		    util_format_get_blocksizebits(pt->format) == 32)
			tile_flags = 0x7a00;
		else
			tile_flags = 0x7000;
		break;
	}

	/* XXX: texture arrays */
	mt->image_nr = (pt->target == PIPE_TEXTURE_CUBE) ? 6 : 1;

	for (l = 0; l <= pt->last_level; l++) {
		struct nv50_miptree_level *lvl = &mt->level[l];
		unsigned nblocksy = util_format_get_nblocksy(pt->format, height);

		lvl->image_offset = CALLOC(mt->image_nr, sizeof(int));
		lvl->pitch = align(util_format_get_stride(pt->format, width), 64);
		lvl->tile_mode = get_tile_mode(nblocksy, depth);

		width = u_minify(width, 1);
		height = u_minify(height, 1);
		depth = u_minify(depth, 1);
	}

	image_alignment  = get_tile_height(mt->level[0].tile_mode) * 64;
	image_alignment *= get_tile_depth(mt->level[0].tile_mode);

	/* NOTE the distinction between arrays of mip-mapped 2D textures and
	 * mip-mapped 3D textures. We can't use image_nr == depth for 3D mip.
	 */
	for (i = 0; i < mt->image_nr; i++) {
		for (l = 0; l <= pt->last_level; l++) {
			struct nv50_miptree_level *lvl = &mt->level[l];
			int size;
			unsigned tile_h = get_tile_height(lvl->tile_mode);
			unsigned tile_d = get_tile_depth(lvl->tile_mode);

			size  = lvl->pitch;
			size *= align(util_format_get_nblocksy(pt->format, u_minify(pt->height0, l)), tile_h);
			size *= align(u_minify(pt->depth0, l), tile_d);

			lvl->image_offset[i] = mt->total_size;

			mt->total_size += size;
		}
		mt->total_size = align(mt->total_size, image_alignment);
	}

	ret = nouveau_bo_new_tile(dev, NOUVEAU_BO_VRAM, 256, mt->total_size,
				  mt->level[0].tile_mode, tile_flags,
				  &mt->base.bo);
	if (ret) {
		for (l = 0; l <= pt->last_level; ++l)
			FREE(mt->level[l].image_offset);
		FREE(mt);
		return NULL;
	}

	return pt;
}
Example #22
0
/**
 * Get the buffers from the server.
 */
static void
dri2_surface_get_buffers(struct native_surface *nsurf, uint buffer_mask)
{
   struct dri2_surface *dri2surf = dri2_surface(nsurf);
   struct dri2_display *dri2dpy = dri2surf->dri2dpy;
   unsigned int dri2atts[NUM_NATIVE_ATTACHMENTS * 2];
   int num_ins, num_outs, att;
   struct x11_drawable_buffer *xbufs;
   uint bpp = util_format_get_blocksizebits(dri2surf->color_format);
   boolean with_format = FALSE; /* never ask for depth/stencil */

   /* We must get the front on servers which doesn't support with format
    * due to a silly bug in core dri2. You can't copy to/from a buffer
    * that you haven't requested and you recive BadValue errors */
   if (dri2surf->dri2dpy->dri_minor < 1) {
      with_format = FALSE;
      buffer_mask |= (1 << NATIVE_ATTACHMENT_FRONT_LEFT);
   }

   /* prepare the attachments */
   num_ins = 0;
   for (att = 0; att < NUM_NATIVE_ATTACHMENTS; att++) {
      if (native_attachment_mask_test(buffer_mask, att)) {
         unsigned int dri2att;

         switch (att) {
         case NATIVE_ATTACHMENT_FRONT_LEFT:
            dri2att = DRI2BufferFrontLeft;
            break;
         case NATIVE_ATTACHMENT_BACK_LEFT:
            dri2att = DRI2BufferBackLeft;
            break;
         case NATIVE_ATTACHMENT_FRONT_RIGHT:
            dri2att = DRI2BufferFrontRight;
            break;
         case NATIVE_ATTACHMENT_BACK_RIGHT:
            dri2att = DRI2BufferBackRight;
            break;
         default:
            assert(0);
            dri2att = 0;
            break;
         }

         dri2atts[num_ins++] = dri2att;
         if (with_format)
            dri2atts[num_ins++] = bpp;
      }
   }
   if (with_format)
      num_ins /= 2;

   xbufs = x11_drawable_get_buffers(dri2dpy->xscr, dri2surf->drawable,
                                    &dri2surf->width, &dri2surf->height,
                                    dri2atts, with_format, num_ins, &num_outs);

   /* we should be able to do better... */
   if (xbufs && dri2surf->last_num_xbufs == num_outs &&
       memcmp(dri2surf->last_xbufs, xbufs, sizeof(*xbufs) * num_outs) == 0) {
      FREE(xbufs);
      dri2surf->client_stamp = dri2surf->server_stamp;
      return;
   }

   dri2_surface_process_drawable_buffers(&dri2surf->base, xbufs, num_outs);

   dri2surf->server_stamp++;
   dri2surf->client_stamp = dri2surf->server_stamp;

   FREE(dri2surf->last_xbufs);
   dri2surf->last_xbufs = xbufs;
   dri2surf->last_num_xbufs = num_outs;
}
void r300_texture_desc_init(struct r300_screen *rscreen,
                            struct r300_resource *tex,
                            const struct pipe_resource *base)
{
    tex->b.b.target = base->target;
    tex->b.b.format = base->format;
    tex->b.b.width0 = base->width0;
    tex->b.b.height0 = base->height0;
    tex->b.b.depth0 = base->depth0;
    tex->b.b.array_size = base->array_size;
    tex->b.b.last_level = base->last_level;
    tex->b.b.nr_samples = base->nr_samples;
    tex->tex.width0 = base->width0;
    tex->tex.height0 = base->height0;
    tex->tex.depth0 = base->depth0;

    /* There is a CB memory addressing hardware bug that limits the width
     * of the MSAA buffer in some cases in R520. In order to get around it,
     * the following code lowers the sample count depending on the format and
     * the width.
     *
     * The only catch is that all MSAA colorbuffers and a zbuffer which are
     * supposed to be used together should always be bound together. Only
     * then the correct minimum sample count of all bound buffers is used
     * for rendering. */
    if (rscreen->caps.is_r500) {
        /* FP16 6x MSAA buffers are limited to a width of 1360 pixels. */
        if ((tex->b.b.format == PIPE_FORMAT_R16G16B16A16_FLOAT ||
             tex->b.b.format == PIPE_FORMAT_R16G16B16X16_FLOAT) &&
            tex->b.b.nr_samples == 6 && tex->b.b.width0 > 1360) {
            tex->b.b.nr_samples = 4;
        }

        /* FP16 4x MSAA buffers are limited to a width of 2048 pixels. */
        if ((tex->b.b.format == PIPE_FORMAT_R16G16B16A16_FLOAT ||
             tex->b.b.format == PIPE_FORMAT_R16G16B16X16_FLOAT) &&
            tex->b.b.nr_samples == 4 && tex->b.b.width0 > 2048) {
            tex->b.b.nr_samples = 2;
        }
    }

    /* 32-bit 6x MSAA buffers are limited to a width of 2720 pixels.
     * This applies to all R300-R500 cards. */
    if (util_format_get_blocksizebits(tex->b.b.format) == 32 &&
        !util_format_is_depth_or_stencil(tex->b.b.format) &&
        tex->b.b.nr_samples == 6 && tex->b.b.width0 > 2720) {
        tex->b.b.nr_samples = 4;
    }

    r300_setup_flags(tex);

    /* Align a 3D NPOT texture to POT. */
    if (base->target == PIPE_TEXTURE_3D && tex->tex.is_npot) {
        tex->tex.width0 = util_next_power_of_two(tex->tex.width0);
        tex->tex.height0 = util_next_power_of_two(tex->tex.height0);
        tex->tex.depth0 = util_next_power_of_two(tex->tex.depth0);
    }

    /* Setup tiling. */
    if (tex->tex.microtile == RADEON_LAYOUT_UNKNOWN) {
        r300_setup_tiling(rscreen, tex);
    }

    r300_setup_cbzb_flags(rscreen, tex);

    /* Setup the miptree description. */
    r300_setup_miptree(rscreen, tex, TRUE);
    /* If the required buffer size is larger than the given max size,
     * try again without the alignment for the CBZB clear. */
    if (tex->buf && tex->tex.size_in_bytes > tex->buf->size) {
        r300_setup_miptree(rscreen, tex, FALSE);

        /* Make sure the buffer we got is large enough. */
        if (tex->tex.size_in_bytes > tex->buf->size) {
            fprintf(stderr,
                "r300: I got a pre-allocated buffer to use it as a texture "
                "storage, but the buffer is too small. I'll use the buffer "
                "anyway, because I can't crash here, but it's dangerous. "
                "This can be a DDX bug. Got: %iB, Need: %iB, Info:\n",
                tex->buf->size, tex->tex.size_in_bytes);
            r300_tex_print_info(tex, "texture_desc_init");
            /* Ooops, what now. Apps will break if we fail this,
             * so just pretend everything's okay. */
        }
    }

    r300_setup_hyperz_properties(rscreen, tex);
    r300_setup_cmask_properties(rscreen, tex);

    if (SCREEN_DBG_ON(rscreen, DBG_TEX))
        r300_tex_print_info(tex, "texture_desc_init");
}
Example #24
0
/**
 * Retrieve __DRIbuffer from the DRI loader.
 */
static __DRIbuffer *
dri2_drawable_get_buffers(struct dri_drawable *drawable,
                          const enum st_attachment_type *atts,
                          unsigned *count)
{
   __DRIdrawable *dri_drawable = drawable->dPriv;
   const __DRIdri2LoaderExtension *loader = drawable->sPriv->dri2.loader;
   boolean with_format;
   __DRIbuffer *buffers;
   int num_buffers;
   unsigned attachments[10];
   unsigned num_attachments, i;

   assert(loader);
   with_format = dri_with_format(drawable->sPriv);

   num_attachments = 0;

   /* for Xserver 1.6.0 (DRI2 version 1) we always need to ask for the front */
   if (!with_format)
      attachments[num_attachments++] = __DRI_BUFFER_FRONT_LEFT;

   for (i = 0; i < *count; i++) {
      enum pipe_format format;
      unsigned bind;
      int att, depth;

      dri_drawable_get_format(drawable, atts[i], &format, &bind);
      if (format == PIPE_FORMAT_NONE)
         continue;

      switch (atts[i]) {
      case ST_ATTACHMENT_FRONT_LEFT:
         /* already added */
         if (!with_format)
            continue;
         att = __DRI_BUFFER_FRONT_LEFT;
         break;
      case ST_ATTACHMENT_BACK_LEFT:
         att = __DRI_BUFFER_BACK_LEFT;
         break;
      case ST_ATTACHMENT_FRONT_RIGHT:
         att = __DRI_BUFFER_FRONT_RIGHT;
         break;
      case ST_ATTACHMENT_BACK_RIGHT:
         att = __DRI_BUFFER_BACK_RIGHT;
         break;
      default:
         continue;
      }

      /*
       * In this switch statement we must support all formats that
       * may occur as the stvis->color_format.
       */
      switch(format) {
      case PIPE_FORMAT_B8G8R8A8_UNORM:
	 depth = 32;
	 break;
      case PIPE_FORMAT_B8G8R8X8_UNORM:
	 depth = 24;
	 break;
      case PIPE_FORMAT_B5G6R5_UNORM:
	 depth = 16;
	 break;
      default:
	 depth = util_format_get_blocksizebits(format);
	 assert(!"Unexpected format in dri2_drawable_get_buffers()");
      }

      attachments[num_attachments++] = att;
      if (with_format) {
         attachments[num_attachments++] = depth;
      }
   }

   if (with_format) {
      num_attachments /= 2;
      buffers = loader->getBuffersWithFormat(dri_drawable,
            &dri_drawable->w, &dri_drawable->h,
            attachments, num_attachments,
            &num_buffers, dri_drawable->loaderPrivate);
   }
   else {
      buffers = loader->getBuffers(dri_drawable,
            &dri_drawable->w, &dri_drawable->h,
            attachments, num_attachments,
            &num_buffers, dri_drawable->loaderPrivate);
   }

   if (buffers)
      *count = num_buffers;

   return buffers;
}
Example #25
0
/**
 * Retrieve __DRIbuffer from the DRI loader.
 */
static __DRIbuffer *
dri2_drawable_get_buffers(struct dri_drawable *drawable,
                          const enum st_attachment_type *statts,
                          unsigned *count)
{
   __DRIdrawable *dri_drawable = drawable->dPriv;
   struct __DRIdri2LoaderExtensionRec *loader = drawable->sPriv->dri2.loader;
   boolean with_format;
   __DRIbuffer *buffers;
   int num_buffers;
   unsigned attachments[10];
   unsigned num_attachments, i;

   assert(loader);
   with_format = dri_with_format(drawable->sPriv);

   num_attachments = 0;

   /* for Xserver 1.6.0 (DRI2 version 1) we always need to ask for the front */
   if (!with_format)
      attachments[num_attachments++] = __DRI_BUFFER_FRONT_LEFT;

   for (i = 0; i < *count; i++) {
      enum pipe_format format;
      unsigned bind;
      int att, bpp;

      dri_drawable_get_format(drawable, statts[i], &format, &bind);
      if (format == PIPE_FORMAT_NONE)
         continue;

      switch (statts[i]) {
      case ST_ATTACHMENT_FRONT_LEFT:
         /* already added */
         if (!with_format)
            continue;
         att = __DRI_BUFFER_FRONT_LEFT;
         break;
      case ST_ATTACHMENT_BACK_LEFT:
         att = __DRI_BUFFER_BACK_LEFT;
         break;
      case ST_ATTACHMENT_FRONT_RIGHT:
         att = __DRI_BUFFER_FRONT_RIGHT;
         break;
      case ST_ATTACHMENT_BACK_RIGHT:
         att = __DRI_BUFFER_BACK_RIGHT;
         break;
      case ST_ATTACHMENT_DEPTH_STENCIL:
         att = __DRI_BUFFER_DEPTH_STENCIL;
         break;
      default:
         att = -1;
         break;
      }

      bpp = util_format_get_blocksizebits(format);

      if (att >= 0) {
         attachments[num_attachments++] = att;
         if (with_format) {
            attachments[num_attachments++] = bpp;
         }
      }
   }

   if (with_format) {
      num_attachments /= 2;
      buffers = loader->getBuffersWithFormat(dri_drawable,
            &dri_drawable->w, &dri_drawable->h,
            attachments, num_attachments,
            &num_buffers, dri_drawable->loaderPrivate);
   }
   else {
      buffers = loader->getBuffers(dri_drawable,
            &dri_drawable->w, &dri_drawable->h,
            attachments, num_attachments,
            &num_buffers, dri_drawable->loaderPrivate);
   }

   if (buffers) {
      /* set one cliprect to cover the whole dri_drawable */
      dri_drawable->x = 0;
      dri_drawable->y = 0;
      dri_drawable->backX = 0;
      dri_drawable->backY = 0;
      dri_drawable->numClipRects = 1;
      dri_drawable->pClipRects[0].x1 = 0;
      dri_drawable->pClipRects[0].y1 = 0;
      dri_drawable->pClipRects[0].x2 = dri_drawable->w;
      dri_drawable->pClipRects[0].y2 = dri_drawable->h;
      dri_drawable->numBackClipRects = 1;
      dri_drawable->pBackClipRects[0].x1 = 0;
      dri_drawable->pBackClipRects[0].y1 = 0;
      dri_drawable->pBackClipRects[0].x2 = dri_drawable->w;
      dri_drawable->pBackClipRects[0].y2 = dri_drawable->h;

      *count = num_buffers;
   }

   return buffers;
}