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; } }
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; }
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; }
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; }
/** * 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; }
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; }
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; } }
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); }
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; }
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; } }
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; }
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; }
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); }
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; } }
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 {
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; } } } }
/* 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; }
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; }
/** * 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"); }
/** * 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; }
/** * 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; }