/** * This is called when we need to set up GL rendering to a new X window. */ static GLboolean intelCreateBuffer(__DRIscreen * driScrnPriv, __DRIdrawable * driDrawPriv, const struct gl_config * mesaVis, GLboolean isPixmap) { struct intel_renderbuffer *rb; mesa_format rgbFormat; struct gl_framebuffer *fb; if (isPixmap) return false; fb = CALLOC_STRUCT(gl_framebuffer); if (!fb) return false; _mesa_initialize_window_framebuffer(fb, mesaVis); if (mesaVis->redBits == 5) rgbFormat = MESA_FORMAT_B5G6R5_UNORM; else if (mesaVis->sRGBCapable) rgbFormat = MESA_FORMAT_B8G8R8A8_SRGB; else if (mesaVis->alphaBits == 0) rgbFormat = MESA_FORMAT_B8G8R8X8_UNORM; else rgbFormat = MESA_FORMAT_B8G8R8A8_UNORM; /* setup the hardware-based renderbuffers */ rb = intel_create_renderbuffer(rgbFormat); _mesa_add_renderbuffer(fb, BUFFER_FRONT_LEFT, &rb->Base.Base); if (mesaVis->doubleBufferMode) { rb = intel_create_renderbuffer(rgbFormat); _mesa_add_renderbuffer(fb, BUFFER_BACK_LEFT, &rb->Base.Base); } /* * Assert here that the gl_config has an expected depth/stencil bit * combination: one of d24/s8, d16/s0, d0/s0. (See intelInitScreen2(), * which constructs the advertised configs.) */ if (mesaVis->depthBits == 24) { assert(mesaVis->stencilBits == 8); /* * Use combined depth/stencil. Note that the renderbuffer is * attached to two attachment points. */ rb = intel_create_private_renderbuffer(MESA_FORMAT_Z24_UNORM_S8_UINT); _mesa_add_renderbuffer(fb, BUFFER_DEPTH, &rb->Base.Base); _mesa_add_renderbuffer(fb, BUFFER_STENCIL, &rb->Base.Base); } else if (mesaVis->depthBits == 16) { assert(mesaVis->stencilBits == 0); rb = intel_create_private_renderbuffer(MESA_FORMAT_Z_UNORM16); _mesa_add_renderbuffer(fb, BUFFER_DEPTH, &rb->Base.Base); } else { assert(mesaVis->depthBits == 0); assert(mesaVis->stencilBits == 0); } /* now add any/all software-based renderbuffers we may need */ _swrast_add_soft_renderbuffers(fb, false, /* never sw color */ false, /* never sw depth */ false, /* never sw stencil */ mesaVis->accumRedBits > 0, false, /* never sw alpha */ false /* never sw aux */ ); driDrawPriv->driverPrivate = fb; return true; }
struct pipe_screen * nv30_screen_create(struct nouveau_device *dev) { struct nv30_screen *screen = CALLOC_STRUCT(nv30_screen); struct pipe_screen *pscreen; struct nouveau_pushbuf *push; struct nv04_fifo *fifo; unsigned oclass = 0; int ret, i; if (!screen) return NULL; switch (dev->chipset & 0xf0) { case 0x30: if (RANKINE_0397_CHIPSET & (1 << (dev->chipset & 0x0f))) oclass = NV30_3D_CLASS; else if (RANKINE_0697_CHIPSET & (1 << (dev->chipset & 0x0f))) oclass = NV34_3D_CLASS; else if (RANKINE_0497_CHIPSET & (1 << (dev->chipset & 0x0f))) oclass = NV35_3D_CLASS; break; case 0x40: if (CURIE_4097_CHIPSET & (1 << (dev->chipset & 0x0f))) oclass = NV40_3D_CLASS; else if (CURIE_4497_CHIPSET & (1 << (dev->chipset & 0x0f))) oclass = NV44_3D_CLASS; break; case 0x60: if (CURIE_4497_CHIPSET6X & (1 << (dev->chipset & 0x0f))) oclass = NV44_3D_CLASS; break; default: break; } if (!oclass) { NOUVEAU_ERR("unknown 3d class for 0x%02x\n", dev->chipset); FREE(screen); return NULL; } pscreen = &screen->base.base; pscreen->destroy = nv30_screen_destroy; pscreen->get_param = nv30_screen_get_param; pscreen->get_paramf = nv30_screen_get_paramf; pscreen->get_shader_param = nv30_screen_get_shader_param; pscreen->context_create = nv30_context_create; pscreen->is_format_supported = nv30_screen_is_format_supported; nv30_resource_screen_init(pscreen); nouveau_screen_init_vdec(&screen->base); screen->base.fence.emit = nv30_screen_fence_emit; screen->base.fence.update = nv30_screen_fence_update; ret = nouveau_screen_init(&screen->base, dev); if (ret) FAIL_SCREEN_INIT("nv30_screen_init failed: %d\n", ret); screen->base.vidmem_bindings |= PIPE_BIND_VERTEX_BUFFER; screen->base.sysmem_bindings |= PIPE_BIND_VERTEX_BUFFER; if (oclass == NV40_3D_CLASS) { screen->base.vidmem_bindings |= PIPE_BIND_INDEX_BUFFER; screen->base.sysmem_bindings |= PIPE_BIND_INDEX_BUFFER; } fifo = screen->base.channel->data; push = screen->base.pushbuf; push->rsvd_kick = 16; ret = nouveau_object_new(screen->base.channel, 0x00000000, NV01_NULL_CLASS, NULL, 0, &screen->null); if (ret) FAIL_SCREEN_INIT("error allocating null object: %d\n", ret); /* DMA_FENCE refuses to accept DMA objects with "adjust" filled in, * this means that the address pointed at by the DMA object must * be 4KiB aligned, which means this object needs to be the first * one allocated on the channel. */ ret = nouveau_object_new(screen->base.channel, 0xbeef1e00, NOUVEAU_NOTIFIER_CLASS, &(struct nv04_notify) { .length = 32 }, sizeof(struct nv04_notify),
static struct gbm_bo * gbm_gallium_drm_bo_import(struct gbm_device *gbm, uint32_t type, void *buffer, uint32_t usage) { struct gbm_gallium_drm_device *gdrm = gbm_gallium_drm_device(gbm); struct gbm_gallium_drm_bo *bo; struct winsys_handle whandle; struct pipe_resource *resource; switch (type) { #if HAVE_WAYLAND_PLATFORM case GBM_BO_IMPORT_WL_BUFFER: { struct wl_drm_buffer *wb = (struct wl_drm_buffer *) buffer; resource = wb->driver_buffer; break; } #endif case GBM_BO_IMPORT_EGL_IMAGE: if (!gdrm->lookup_egl_image) return NULL; resource = gdrm->lookup_egl_image(gdrm->lookup_egl_image_data, buffer); if (resource == NULL) return NULL; break; default: return NULL; } bo = CALLOC_STRUCT(gbm_gallium_drm_bo); if (bo == NULL) return NULL; bo->base.base.gbm = gbm; bo->base.base.width = resource->width0; bo->base.base.height = resource->height0; switch (resource->format) { case PIPE_FORMAT_B8G8R8X8_UNORM: bo->base.base.format = GBM_BO_FORMAT_XRGB8888; break; case PIPE_FORMAT_B8G8R8A8_UNORM: bo->base.base.format = GBM_BO_FORMAT_ARGB8888; break; default: FREE(bo); return NULL; } pipe_resource_reference(&bo->resource, resource); memset(&whandle, 0, sizeof(whandle)); whandle.type = DRM_API_HANDLE_TYPE_KMS; gdrm->screen->resource_get_handle(gdrm->screen, bo->resource, &whandle); bo->base.base.handle.u32 = whandle.handle; bo->base.base.stride = whandle.stride; return &bo->base.base; }
/** * Create a new XMesaContext. * \param v the XMesaVisual * \param share_list another XMesaContext with which to share display * lists or NULL if no sharing is wanted. * \return an XMesaContext or NULL if error. */ PUBLIC XMesaContext XMesaCreateContext( XMesaVisual v, XMesaContext share_list, GLuint major, GLuint minor, GLuint profileMask, GLuint contextFlags) { XMesaDisplay xmdpy = xmesa_init_display(v->display); struct st_context_attribs attribs; enum st_context_error ctx_err = 0; XMesaContext c; if (!xmdpy) return NULL; /* Note: the XMesaContext contains a Mesa struct gl_context struct (inheritance) */ c = (XMesaContext) CALLOC_STRUCT(xmesa_context); if (!c) return NULL; c->xm_visual = v; c->xm_buffer = NULL; /* set later by XMesaMakeCurrent */ c->xm_read_buffer = NULL; memset(&attribs, 0, sizeof(attribs)); attribs.visual = v->stvis; attribs.major = major; attribs.minor = minor; if (contextFlags & GLX_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB) attribs.flags |= ST_CONTEXT_FLAG_FORWARD_COMPATIBLE; if (contextFlags & GLX_CONTEXT_DEBUG_BIT_ARB) attribs.flags |= ST_CONTEXT_FLAG_DEBUG; if (contextFlags & GLX_CONTEXT_ROBUST_ACCESS_BIT_ARB) attribs.flags |= ST_CONTEXT_FLAG_ROBUST_ACCESS; /* There are no profiles before OpenGL 3.2. The * GLX_ARB_create_context_profile spec says: * * "If the requested OpenGL version is less than 3.2, * GLX_CONTEXT_PROFILE_MASK_ARB is ignored and the functionality of the * context is determined solely by the requested version." * * The spec also says: * * "The default value for GLX_CONTEXT_PROFILE_MASK_ARB is * GLX_CONTEXT_CORE_PROFILE_BIT_ARB." */ attribs.profile = ST_PROFILE_DEFAULT; if ((major > 3 || (major == 3 && minor >= 2)) && ((profileMask & GLX_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB) == 0)) attribs.profile = ST_PROFILE_OPENGL_CORE; c->st = stapi->create_context(stapi, xmdpy->smapi, &attribs, &ctx_err, (share_list) ? share_list->st : NULL); if (c->st == NULL) goto fail; c->st->st_manager_private = (void *) c; return c; fail: if (c->st) c->st->destroy(c->st); free(c); return NULL; }
struct pipe_context* r300_create_context(struct pipe_screen* screen, void *priv) { struct r300_context* r300 = CALLOC_STRUCT(r300_context); struct r300_screen* r300screen = r300_screen(screen); struct radeon_winsys *rws = r300screen->rws; if (!r300) return NULL; r300->rws = rws; r300->screen = r300screen; r300->context.screen = screen; r300->context.priv = priv; r300->context.destroy = r300_destroy_context; util_slab_create(&r300->pool_transfers, sizeof(struct pipe_transfer), 64, UTIL_SLAB_SINGLETHREADED); r300->cs = rws->cs_create(rws, RING_GFX, NULL); if (r300->cs == NULL) goto fail; if (!r300screen->caps.has_tcl) { /* Create a Draw. This is used for SW TCL. */ r300->draw = draw_create(&r300->context); if (r300->draw == NULL) goto fail; /* Enable our renderer. */ draw_set_rasterize_stage(r300->draw, r300_draw_stage(r300)); /* Disable converting points/lines to triangles. */ draw_wide_line_threshold(r300->draw, 10000000.f); draw_wide_point_threshold(r300->draw, 10000000.f); draw_wide_point_sprites(r300->draw, FALSE); draw_enable_line_stipple(r300->draw, TRUE); draw_enable_point_sprites(r300->draw, FALSE); } if (!r300_setup_atoms(r300)) goto fail; r300_init_blit_functions(r300); r300_init_flush_functions(r300); r300_init_query_functions(r300); r300_init_state_functions(r300); r300_init_resource_functions(r300); r300_init_render_functions(r300); r300_init_states(&r300->context); r300->context.create_video_decoder = vl_create_decoder; r300->context.create_video_buffer = vl_video_buffer_create; if (r300screen->caps.has_tcl) { r300->uploader = u_upload_create(&r300->context, 256 * 1024, 4, PIPE_BIND_INDEX_BUFFER); } r300->blitter = util_blitter_create(&r300->context); if (r300->blitter == NULL) goto fail; r300->blitter->draw_rectangle = r300_blitter_draw_rectangle; rws->cs_set_flush_callback(r300->cs, r300_flush_callback, r300); /* The KIL opcode needs the first texture unit to be enabled * on r3xx-r4xx. In order to calm down the CS checker, we bind this * dummy texture there. */ if (!r300->screen->caps.is_r500) { struct pipe_resource *tex; struct pipe_resource rtempl = {{0}}; struct pipe_sampler_view vtempl = {{0}}; rtempl.target = PIPE_TEXTURE_2D; rtempl.format = PIPE_FORMAT_I8_UNORM; rtempl.usage = PIPE_USAGE_IMMUTABLE; rtempl.width0 = 1; rtempl.height0 = 1; rtempl.depth0 = 1; tex = screen->resource_create(screen, &rtempl); u_sampler_view_default_template(&vtempl, tex, tex->format); r300->texkill_sampler = (struct r300_sampler_view*) r300->context.create_sampler_view(&r300->context, tex, &vtempl); pipe_resource_reference(&tex, NULL); } if (r300screen->caps.has_tcl) { struct pipe_resource vb; memset(&vb, 0, sizeof(vb)); vb.target = PIPE_BUFFER; vb.format = PIPE_FORMAT_R8_UNORM; vb.usage = PIPE_USAGE_STATIC; vb.width0 = sizeof(float) * 16; vb.height0 = 1; vb.depth0 = 1; r300->dummy_vb.buffer = screen->resource_create(screen, &vb); r300->context.set_vertex_buffers(&r300->context, 0, 1, &r300->dummy_vb); } { struct pipe_depth_stencil_alpha_state dsa; memset(&dsa, 0, sizeof(dsa)); dsa.depth.writemask = 1; r300->dsa_decompress_zmask = r300->context.create_depth_stencil_alpha_state(&r300->context, &dsa); } r300->hyperz_time_of_last_flush = os_time_get(); /* Register allocator state */ rc_init_regalloc_state(&r300->fs_regalloc_state); /* Print driver info. */ #ifdef DEBUG { #else if (DBG_ON(r300, DBG_INFO)) { #endif fprintf(stderr, "r300: DRM version: %d.%d.%d, Name: %s, ID: 0x%04x, GB: %d, Z: %d\n" "r300: GART size: %d MB, VRAM size: %d MB\n" "r300: AA compression RAM: %s, Z compression RAM: %s, HiZ RAM: %s\n", r300->screen->info.drm_major, r300->screen->info.drm_minor, r300->screen->info.drm_patchlevel, screen->get_name(screen), r300->screen->info.pci_id, r300->screen->info.r300_num_gb_pipes, r300->screen->info.r300_num_z_pipes, r300->screen->info.gart_size >> 20, r300->screen->info.vram_size >> 20, "YES", /* XXX really? */ r300->screen->caps.zmask_ram ? "YES" : "NO", r300->screen->caps.hiz_ram ? "YES" : "NO"); } return &r300->context; fail: r300_destroy_context(&r300->context); return NULL; }
void * fd4_zsa_state_create(struct pipe_context *pctx, const struct pipe_depth_stencil_alpha_state *cso) { struct fd4_zsa_stateobj *so; so = CALLOC_STRUCT(fd4_zsa_stateobj); if (!so) return NULL; so->base = *cso; so->rb_depth_control |= A4XX_RB_DEPTH_CONTROL_ZFUNC(cso->depth.func); /* maps 1:1 */ if (cso->depth.enabled) so->rb_depth_control |= A4XX_RB_DEPTH_CONTROL_Z_ENABLE | A4XX_RB_DEPTH_CONTROL_Z_TEST_ENABLE; if (cso->depth.writemask) so->rb_depth_control |= A4XX_RB_DEPTH_CONTROL_Z_WRITE_ENABLE; if (cso->stencil[0].enabled) { const struct pipe_stencil_state *s = &cso->stencil[0]; so->rb_stencil_control |= A4XX_RB_STENCIL_CONTROL_STENCIL_READ | A4XX_RB_STENCIL_CONTROL_STENCIL_ENABLE | A4XX_RB_STENCIL_CONTROL_FUNC(s->func) | /* maps 1:1 */ A4XX_RB_STENCIL_CONTROL_FAIL(fd_stencil_op(s->fail_op)) | A4XX_RB_STENCIL_CONTROL_ZPASS(fd_stencil_op(s->zpass_op)) | A4XX_RB_STENCIL_CONTROL_ZFAIL(fd_stencil_op(s->zfail_op)); so->rb_stencil_control2 |= A4XX_RB_STENCIL_CONTROL2_STENCIL_BUFFER; so->rb_stencilrefmask |= 0xff000000 | /* ??? */ A4XX_RB_STENCILREFMASK_STENCILWRITEMASK(s->writemask) | A4XX_RB_STENCILREFMASK_STENCILMASK(s->valuemask); if (cso->stencil[1].enabled) { const struct pipe_stencil_state *bs = &cso->stencil[1]; so->rb_stencil_control |= A4XX_RB_STENCIL_CONTROL_STENCIL_ENABLE_BF | A4XX_RB_STENCIL_CONTROL_FUNC_BF(bs->func) | /* maps 1:1 */ A4XX_RB_STENCIL_CONTROL_FAIL_BF(fd_stencil_op(bs->fail_op)) | A4XX_RB_STENCIL_CONTROL_ZPASS_BF(fd_stencil_op(bs->zpass_op)) | A4XX_RB_STENCIL_CONTROL_ZFAIL_BF(fd_stencil_op(bs->zfail_op)); so->rb_stencilrefmask_bf |= 0xff000000 | /* ??? */ A4XX_RB_STENCILREFMASK_BF_STENCILWRITEMASK(bs->writemask) | A4XX_RB_STENCILREFMASK_BF_STENCILMASK(bs->valuemask); } } if (cso->alpha.enabled) { uint32_t ref = cso->alpha.ref_value * 255.0; so->gras_alpha_control = A4XX_GRAS_ALPHA_CONTROL_ALPHA_TEST_ENABLE; so->rb_alpha_control = A4XX_RB_ALPHA_CONTROL_ALPHA_TEST | A4XX_RB_ALPHA_CONTROL_ALPHA_REF(ref) | A4XX_RB_ALPHA_CONTROL_ALPHA_TEST_FUNC(cso->alpha.func); so->rb_depth_control |= A4XX_RB_DEPTH_CONTROL_EARLY_Z_DISABLE; } return so; }
/* XXX: Still implementing this as if it was a screen function, but * can now modify it to queue transfers on the context. */ static struct pipe_transfer * svga_texture_get_transfer(struct pipe_context *pipe, struct pipe_resource *texture, unsigned level, unsigned usage, const struct pipe_box *box) { struct svga_context *svga = svga_context(pipe); struct svga_screen *ss = svga_screen(pipe->screen); struct svga_winsys_screen *sws = ss->sws; struct svga_transfer *st; unsigned nblocksx = util_format_get_nblocksx(texture->format, box->width); unsigned nblocksy = util_format_get_nblocksy(texture->format, box->height); /* We can't map texture storage directly */ if (usage & PIPE_TRANSFER_MAP_DIRECTLY) return NULL; assert(box->depth == 1); st = CALLOC_STRUCT(svga_transfer); if (!st) return NULL; pipe_resource_reference(&st->base.resource, texture); st->base.level = level; st->base.usage = usage; st->base.box = *box; st->base.stride = nblocksx*util_format_get_blocksize(texture->format); st->base.layer_stride = 0; st->hw_nblocksy = nblocksy; st->hwbuf = svga_winsys_buffer_create(svga, 1, 0, st->hw_nblocksy*st->base.stride); while(!st->hwbuf && (st->hw_nblocksy /= 2)) { st->hwbuf = svga_winsys_buffer_create(svga, 1, 0, st->hw_nblocksy*st->base.stride); } if(!st->hwbuf) goto no_hwbuf; if(st->hw_nblocksy < nblocksy) { /* We couldn't allocate a hardware buffer big enough for the transfer, * so allocate regular malloc memory instead */ if (0) { debug_printf("%s: failed to allocate %u KB of DMA, " "splitting into %u x %u KB DMA transfers\n", __FUNCTION__, (nblocksy*st->base.stride + 1023)/1024, (nblocksy + st->hw_nblocksy - 1)/st->hw_nblocksy, (st->hw_nblocksy*st->base.stride + 1023)/1024); } st->swbuf = MALLOC(nblocksy*st->base.stride); if(!st->swbuf) goto no_swbuf; } if (usage & PIPE_TRANSFER_READ) { SVGA3dSurfaceDMAFlags flags; memset(&flags, 0, sizeof flags); svga_transfer_dma(svga, st, SVGA3D_READ_HOST_VRAM, flags); } return &st->base; no_swbuf: sws->buffer_destroy(sws, st->hwbuf); no_hwbuf: FREE(st); return NULL; }
/* Allocate 2D texture or render target resource */ static struct pipe_resource * etna_screen_resource_create(struct pipe_screen *screen, const struct pipe_resource *templat) { struct etna_screen *priv = etna_screen(screen); assert(templat); unsigned element_size = util_format_get_blocksize(templat->format); if(!element_size) return NULL; /* Check input */ if(templat->target == PIPE_TEXTURE_CUBE) { assert(templat->array_size == 6); } else if (templat->target == PIPE_BUFFER) { assert(templat->format == PIPE_FORMAT_R8_UNORM); /* bytes; want TYPELESS or similar */ assert(templat->array_size == 1); assert(templat->height0 == 1); assert(templat->depth0 == 1); assert(templat->array_size == 1); assert(templat->last_level == 0); } else { assert(templat->array_size == 1); } assert(templat->width0 != 0); assert(templat->height0 != 0); assert(templat->depth0 != 0); assert(templat->array_size != 0); /* Figure out what tiling to use -- for now, assume that textures cannot be supertiled, and cannot be linear. * There is a feature flag SUPERTILED_TEXTURE (not supported on any known hw) that may allow this, as well * as LINEAR_TEXTURE_SUPPORT (supported on gc880 and gc2000 at least), but not sure how it works. * Buffers always have LINEAR layout. */ unsigned layout = ETNA_LAYOUT_LINEAR; if(templat->target != PIPE_BUFFER) { if(!(templat->bind & PIPE_BIND_SAMPLER_VIEW) && priv->specs.can_supertile && !DBG_ENABLED(ETNA_DBG_NO_SUPERTILE)) layout = ETNA_LAYOUT_SUPER_TILED; else layout = ETNA_LAYOUT_TILED; } /* XXX multi tiled formats */ /* Determine scaling for antialiasing, allow override using debug flag */ int nr_samples = templat->nr_samples; if((templat->bind & (PIPE_BIND_RENDER_TARGET | PIPE_BIND_DEPTH_STENCIL)) && !(templat->bind & PIPE_BIND_SAMPLER_VIEW)) { if(DBG_ENABLED(ETNA_DBG_MSAA_2X)) nr_samples = 2; if(DBG_ENABLED(ETNA_DBG_MSAA_4X)) nr_samples = 4; } int msaa_xscale = 1, msaa_yscale = 1; if(!translate_samples_to_xyscale(nr_samples, &msaa_xscale, &msaa_yscale, NULL)) { /* Number of samples not supported */ assert(0); } /* Determine needed padding (alignment of height/width) */ unsigned paddingX = 0, paddingY = 0; unsigned halign = TEXTURE_HALIGN_FOUR; etna_layout_multiple(layout, priv->dev->chip.pixel_pipes, (templat->bind & PIPE_BIND_SAMPLER_VIEW) && !VIV_FEATURE(priv->dev, chipMinorFeatures1, TEXTURE_HALIGN), &paddingX, &paddingY, &halign); assert(paddingX && paddingY); /* determine mipmap levels */ struct etna_resource *resource = CALLOC_STRUCT(etna_resource); int max_mip_level = templat->last_level; if(unlikely(max_mip_level >= ETNA_NUM_LOD)) /* max LOD supported by hw */ max_mip_level = ETNA_NUM_LOD - 1; /* take care about DXTx formats, which have a divSize of non-1x1 * also: lower mipmaps are still 4x4 due to tiling. In as sense, compressed formats are already tiled. * XXX UYVY formats? */ unsigned divSizeX = util_format_get_blockwidth(templat->format); unsigned divSizeY = util_format_get_blockheight(templat->format); unsigned ix = 0; unsigned x = templat->width0, y = templat->height0; unsigned offset = 0; while(true) { struct etna_resource_level *mip = &resource->levels[ix]; mip->width = x; mip->height = y; mip->padded_width = align(x * msaa_xscale, paddingX); mip->padded_height = align(y * msaa_yscale, paddingY); mip->stride = align(mip->padded_width, divSizeX)/divSizeX * element_size; mip->offset = offset; mip->layer_stride = align(mip->padded_width, divSizeX)/divSizeX * align(mip->padded_height, divSizeY)/divSizeY * element_size; mip->size = templat->array_size * mip->layer_stride; offset += align(mip->size, ETNA_PE_ALIGNMENT); /* align mipmaps to 64 bytes to be able to render to them */ if(ix == max_mip_level || (x == 1 && y == 1)) break; // stop at last level x = MAX2(x >> 1, 1); y = MAX2(y >> 1, 1); ix += 1; } /* Determine memory size, and whether to create a tile status */ size_t rt_size = offset; /* determine memory type */ enum viv_surf_type memtype = VIV_SURF_UNKNOWN; if(templat->bind & PIPE_BIND_SAMPLER_VIEW) memtype = VIV_SURF_TEXTURE; else if(templat->bind & PIPE_BIND_RENDER_TARGET) memtype = VIV_SURF_RENDER_TARGET; else if(templat->bind & PIPE_BIND_DEPTH_STENCIL) memtype = VIV_SURF_DEPTH; else if(templat->bind & PIPE_BIND_INDEX_BUFFER) memtype = VIV_SURF_INDEX; else if(templat->bind & PIPE_BIND_VERTEX_BUFFER) memtype = VIV_SURF_VERTEX; DBG_F(ETNA_DBG_RESOURCE_MSGS, "%p: Allocate surface of %ix%i (padded to %ix%i) of format %s (%i bpe %ix%i), size %08zx flags %08x, memtype %i", resource, templat->width0, templat->height0, resource->levels[0].padded_width, resource->levels[0].padded_height, util_format_name(templat->format), element_size, divSizeX, divSizeY, rt_size, templat->bind, memtype); struct etna_vidmem *rt = 0; if(unlikely(etna_vidmem_alloc_linear(priv->dev, &rt, rt_size, memtype, VIV_POOL_DEFAULT, true) != ETNA_OK)) { BUG("Problem allocating video memory for resource"); return NULL; } resource->base = *templat; resource->base.last_level = ix; /* real last mipmap level */ resource->base.screen = screen; resource->base.nr_samples = nr_samples; resource->layout = layout; resource->halign = halign; resource->surface = rt; resource->ts = 0; /* TS is only created when first bound to surface */ pipe_reference_init(&resource->base.reference, 1); if(DBG_ENABLED(ETNA_DBG_ZERO)) { memset(resource->surface->logical, 0, rt_size); } for(unsigned ix=0; ix<=resource->base.last_level; ++ix) { struct etna_resource_level *mip = &resource->levels[ix]; mip->address = resource->surface->address + mip->offset; mip->logical = resource->surface->logical + mip->offset; DBG_F(ETNA_DBG_RESOURCE_MSGS, " %08x level %i: %ix%i (%i) stride=%i layer_stride=%i", (int)mip->address, ix, (int)mip->width, (int)mip->height, (int)mip->size, (int)mip->stride, (int)mip->layer_stride); } return &resource->base; }
struct svga_sampler_view * svga_get_tex_sampler_view(struct pipe_context *pipe, struct pipe_resource *pt, unsigned min_lod, unsigned max_lod) { struct svga_context *svga = svga_context(pipe); struct svga_screen *ss = svga_screen(pipe->screen); struct svga_texture *tex = svga_texture(pt); struct svga_sampler_view *sv = NULL; SVGA3dSurface1Flags flags = SVGA3D_SURFACE_HINT_TEXTURE; SVGA3dSurfaceFormat format = svga_translate_format(ss, pt->format, PIPE_BIND_SAMPLER_VIEW); boolean view = TRUE; assert(pt); assert(min_lod <= max_lod); assert(max_lod <= pt->last_level); assert(!svga_have_vgpu10(svga)); /* Is a view needed */ { /* * Can't control max lod. For first level views and when we only * look at one level we disable mip filtering to achive the same * results as a view. */ if (min_lod == 0 && max_lod >= pt->last_level) view = FALSE; if (ss->debug.no_sampler_view) view = FALSE; if (ss->debug.force_sampler_view) view = TRUE; } /* First try the cache */ if (view) { mtx_lock(&ss->tex_mutex); if (tex->cached_view && tex->cached_view->min_lod == min_lod && tex->cached_view->max_lod == max_lod) { svga_sampler_view_reference(&sv, tex->cached_view); mtx_unlock(&ss->tex_mutex); SVGA_DBG(DEBUG_VIEWS, "svga: Sampler view: reuse %p, %u %u, last %u\n", pt, min_lod, max_lod, pt->last_level); svga_validate_sampler_view(svga_context(pipe), sv); return sv; } mtx_unlock(&ss->tex_mutex); } sv = CALLOC_STRUCT(svga_sampler_view); if (!sv) return NULL; pipe_reference_init(&sv->reference, 1); /* Note: we're not refcounting the texture resource here to avoid * a circular dependency. */ sv->texture = pt; sv->min_lod = min_lod; sv->max_lod = max_lod; /* No view needed just use the whole texture */ if (!view) { SVGA_DBG(DEBUG_VIEWS, "svga: Sampler view: no %p, mips %u..%u, nr %u, size (%ux%ux%u), last %u\n", pt, min_lod, max_lod, max_lod - min_lod + 1, pt->width0, pt->height0, pt->depth0, pt->last_level); sv->key.cachable = 0; sv->handle = tex->handle; debug_reference(&sv->reference, (debug_reference_descriptor)svga_debug_describe_sampler_view, 0); return sv; } SVGA_DBG(DEBUG_VIEWS, "svga: Sampler view: yes %p, mips %u..%u, nr %u, size (%ux%ux%u), last %u\n", pt, min_lod, max_lod, max_lod - min_lod + 1, pt->width0, pt->height0, pt->depth0, pt->last_level); sv->age = tex->age; sv->handle = svga_texture_view_surface(svga, tex, PIPE_BIND_SAMPLER_VIEW, flags, format, min_lod, max_lod - min_lod + 1, -1, 1, -1, FALSE, &sv->key); if (!sv->handle) { sv->key.cachable = 0; sv->handle = tex->handle; debug_reference(&sv->reference, (debug_reference_descriptor) svga_debug_describe_sampler_view, 0); return sv; } mtx_lock(&ss->tex_mutex); svga_sampler_view_reference(&tex->cached_view, sv); mtx_unlock(&ss->tex_mutex); debug_reference(&sv->reference, (debug_reference_descriptor) svga_debug_describe_sampler_view, 0); return sv; }
struct pipe_query *r600_create_batch_query(struct pipe_context *ctx, unsigned num_queries, unsigned *query_types) { struct r600_common_context *rctx = (struct r600_common_context *)ctx; struct r600_common_screen *screen = rctx->screen; struct r600_perfcounters *pc = screen->perfcounters; struct r600_perfcounter_block *block; struct r600_pc_group *group; struct r600_query_pc *query; unsigned base_gid, sub_gid, sub_index; unsigned i, j; if (!pc) return NULL; query = CALLOC_STRUCT(r600_query_pc); if (!query) return NULL; query->b.b.ops = &batch_query_ops; query->b.ops = &batch_query_hw_ops; query->num_counters = num_queries; /* Collect selectors per group */ for (i = 0; i < num_queries; ++i) { unsigned sub_gid; if (query_types[i] < R600_QUERY_FIRST_PERFCOUNTER) goto error; block = lookup_counter(pc, query_types[i] - R600_QUERY_FIRST_PERFCOUNTER, &base_gid, &sub_index); if (!block) goto error; sub_gid = sub_index / block->num_selectors; sub_index = sub_index % block->num_selectors; group = get_group_state(screen, query, block, sub_gid); if (!group) goto error; if (group->num_counters >= block->num_counters) { fprintf(stderr, "perfcounter group %s: too many selected\n", block->basename); goto error; } group->selectors[group->num_counters] = sub_index; ++group->num_counters; } /* Compute result bases and CS size per group */ query->b.num_cs_dw_begin = pc->num_start_cs_dwords; query->b.num_cs_dw_end = pc->num_stop_cs_dwords; query->b.num_cs_dw_begin += pc->num_instance_cs_dwords; /* conservative */ query->b.num_cs_dw_end += pc->num_instance_cs_dwords; i = 0; for (group = query->groups; group; group = group->next) { struct r600_perfcounter_block *block = group->block; unsigned select_dw, read_dw; unsigned instances = 1; if ((block->flags & R600_PC_BLOCK_SE) && group->se < 0) instances = rctx->screen->info.max_se; if (group->instance < 0) instances *= block->num_instances; group->result_base = i; query->b.result_size += sizeof(uint64_t) * instances * group->num_counters; i += instances * group->num_counters; pc->get_size(block, group->num_counters, group->selectors, &select_dw, &read_dw); query->b.num_cs_dw_begin += select_dw; query->b.num_cs_dw_end += instances * read_dw; query->b.num_cs_dw_begin += pc->num_instance_cs_dwords; /* conservative */ query->b.num_cs_dw_end += instances * pc->num_instance_cs_dwords; } if (query->shaders) { if (query->shaders == R600_PC_SHADERS_WINDOWING) query->shaders = 0xffffffff; query->b.num_cs_dw_begin += pc->num_shaders_cs_dwords; } /* Map user-supplied query array to result indices */ query->counters = CALLOC(num_queries, sizeof(*query->counters)); for (i = 0; i < num_queries; ++i) { struct r600_pc_counter *counter = &query->counters[i]; struct r600_perfcounter_block *block; block = lookup_counter(pc, query_types[i] - R600_QUERY_FIRST_PERFCOUNTER, &base_gid, &sub_index); sub_gid = sub_index / block->num_selectors; sub_index = sub_index % block->num_selectors; group = get_group_state(screen, query, block, sub_gid); assert(group != NULL); for (j = 0; j < group->num_counters; ++j) { if (group->selectors[j] == sub_index) break; } counter->base = group->result_base + j; counter->stride = group->num_counters; counter->qwords = 1; if ((block->flags & R600_PC_BLOCK_SE) && group->se < 0) counter->qwords = screen->info.max_se; if (group->instance < 0) counter->qwords *= block->num_instances; } if (!r600_query_hw_init(rctx, &query->b)) goto error; return (struct pipe_query *)query; error: r600_pc_query_destroy(rctx, &query->b.b); return NULL; }
uint32 vmw_ioctl_gb_surface_create(struct vmw_winsys_screen *vws, SVGA3dSurfaceFlags flags, SVGA3dSurfaceFormat format, unsigned usage, SVGA3dSize size, uint32_t numFaces, uint32_t numMipLevels, uint32_t buffer_handle, struct vmw_region **p_region) { union drm_vmw_gb_surface_create_arg s_arg; struct drm_vmw_gb_surface_create_req *req = &s_arg.req; struct drm_vmw_gb_surface_create_rep *rep = &s_arg.rep; struct vmw_region *region = NULL; int ret; vmw_printf("%s flags %d format %d\n", __FUNCTION__, flags, format); if (p_region) { region = CALLOC_STRUCT(vmw_region); if (!region) return SVGA3D_INVALID_ID; } memset(&s_arg, 0, sizeof(s_arg)); if (flags & SVGA3D_SURFACE_HINT_SCANOUT) { req->svga3d_flags = (uint32_t) (flags & ~SVGA3D_SURFACE_HINT_SCANOUT); req->drm_surface_flags = drm_vmw_surface_flag_scanout; } else { req->svga3d_flags = (uint32_t) flags; } req->format = (uint32_t) format; if (usage & SVGA_SURFACE_USAGE_SHARED) req->drm_surface_flags |= drm_vmw_surface_flag_shareable; req->drm_surface_flags |= drm_vmw_surface_flag_create_buffer; assert(numFaces * numMipLevels < DRM_VMW_MAX_SURFACE_FACES* DRM_VMW_MAX_MIP_LEVELS); req->base_size.width = size.width; req->base_size.height = size.height; req->base_size.depth = size.depth; req->mip_levels = numMipLevels; req->multisample_count = 0; req->autogen_filter = SVGA3D_TEX_FILTER_NONE; if (buffer_handle) req->buffer_handle = buffer_handle; else req->buffer_handle = SVGA3D_INVALID_ID; ret = drmCommandWriteRead(vws->ioctl.drm_fd, DRM_VMW_GB_SURFACE_CREATE, &s_arg, sizeof(s_arg)); if (ret) goto out_fail_create; if (p_region) { region->handle = rep->buffer_handle; region->map_handle = rep->buffer_map_handle; region->drm_fd = vws->ioctl.drm_fd; region->size = rep->backup_size; *p_region = region; } vmw_printf("Surface id is %d\n", rep->sid); return rep->handle; out_fail_create: if (region) FREE(region); return SVGA3D_INVALID_ID; }
static struct r600_pc_group *get_group_state(struct r600_common_screen *screen, struct r600_query_pc *query, struct r600_perfcounter_block *block, unsigned sub_gid) { struct r600_pc_group *group = query->groups; while (group) { if (group->block == block && group->sub_gid == sub_gid) return group; group = group->next; } group = CALLOC_STRUCT(r600_pc_group); if (!group) return NULL; group->block = block; group->sub_gid = sub_gid; if (block->flags & R600_PC_BLOCK_SHADER) { unsigned sub_gids = block->num_instances; unsigned shader_id; unsigned shaders; unsigned query_shaders; if (block->flags & R600_PC_BLOCK_SE_GROUPS) sub_gids = sub_gids * screen->info.max_se; shader_id = sub_gid / sub_gids; sub_gid = sub_gid % sub_gids; shaders = screen->perfcounters->shader_type_bits[shader_id]; query_shaders = query->shaders & ~R600_PC_SHADERS_WINDOWING; if (query_shaders && query_shaders != shaders) { fprintf(stderr, "r600_perfcounter: incompatible shader groups\n"); FREE(group); return NULL; } query->shaders = shaders; } if (block->flags & R600_PC_BLOCK_SHADER_WINDOWED && !query->shaders) { // A non-zero value in query->shaders ensures that the shader // masking is reset unless the user explicitly requests one. query->shaders = R600_PC_SHADERS_WINDOWING; } if (block->flags & R600_PC_BLOCK_SE_GROUPS) { group->se = sub_gid / block->num_instances; sub_gid = sub_gid % block->num_instances; } else { group->se = -1; } if (block->flags & R600_PC_BLOCK_INSTANCE_GROUPS) { group->instance = sub_gid; } else { group->instance = -1; } group->next = query->groups; query->groups = group; return group; }
/** * Allocate a new swrast_texture_image (a subclass of gl_texture_image). * Called via ctx->Driver.NewTextureImage(). */ struct gl_texture_image * _swrast_new_texture_image( struct gl_context *ctx ) { (void) ctx; return (struct gl_texture_image *) CALLOC_STRUCT(swrast_texture_image); }
void * fd5_zsa_state_create(struct pipe_context *pctx, const struct pipe_depth_stencil_alpha_state *cso) { struct fd5_zsa_stateobj *so; so = CALLOC_STRUCT(fd5_zsa_stateobj); if (!so) return NULL; so->base = *cso; switch (cso->depth.func) { case PIPE_FUNC_LESS: case PIPE_FUNC_LEQUAL: so->gras_lrz_cntl = A5XX_GRAS_LRZ_CNTL_ENABLE; break; case PIPE_FUNC_GREATER: case PIPE_FUNC_GEQUAL: so->gras_lrz_cntl = A5XX_GRAS_LRZ_CNTL_ENABLE | A5XX_GRAS_LRZ_CNTL_GREATER; break; default: /* LRZ not enabled */ so->gras_lrz_cntl = 0; break; } if (!(cso->stencil->enabled || cso->alpha.enabled || !cso->depth.writemask)) so->lrz_write = true; so->rb_depth_cntl |= A5XX_RB_DEPTH_CNTL_ZFUNC(cso->depth.func); /* maps 1:1 */ if (cso->depth.enabled) so->rb_depth_cntl |= A5XX_RB_DEPTH_CNTL_Z_ENABLE | A5XX_RB_DEPTH_CNTL_Z_TEST_ENABLE; if (cso->depth.writemask) so->rb_depth_cntl |= A5XX_RB_DEPTH_CNTL_Z_WRITE_ENABLE; if (cso->stencil[0].enabled) { const struct pipe_stencil_state *s = &cso->stencil[0]; so->rb_stencil_control |= A5XX_RB_STENCIL_CONTROL_STENCIL_READ | A5XX_RB_STENCIL_CONTROL_STENCIL_ENABLE | A5XX_RB_STENCIL_CONTROL_FUNC(s->func) | /* maps 1:1 */ A5XX_RB_STENCIL_CONTROL_FAIL(fd_stencil_op(s->fail_op)) | A5XX_RB_STENCIL_CONTROL_ZPASS(fd_stencil_op(s->zpass_op)) | A5XX_RB_STENCIL_CONTROL_ZFAIL(fd_stencil_op(s->zfail_op)); so->rb_stencilrefmask |= A5XX_RB_STENCILREFMASK_STENCILWRITEMASK(s->writemask) | A5XX_RB_STENCILREFMASK_STENCILMASK(s->valuemask); if (cso->stencil[1].enabled) { const struct pipe_stencil_state *bs = &cso->stencil[1]; so->rb_stencil_control |= A5XX_RB_STENCIL_CONTROL_STENCIL_ENABLE_BF | A5XX_RB_STENCIL_CONTROL_FUNC_BF(bs->func) | /* maps 1:1 */ A5XX_RB_STENCIL_CONTROL_FAIL_BF(fd_stencil_op(bs->fail_op)) | A5XX_RB_STENCIL_CONTROL_ZPASS_BF(fd_stencil_op(bs->zpass_op)) | A5XX_RB_STENCIL_CONTROL_ZFAIL_BF(fd_stencil_op(bs->zfail_op)); so->rb_stencilrefmask_bf |= A5XX_RB_STENCILREFMASK_BF_STENCILWRITEMASK(bs->writemask) | A5XX_RB_STENCILREFMASK_BF_STENCILMASK(bs->valuemask); } } if (cso->alpha.enabled) { uint32_t ref = cso->alpha.ref_value * 255.0; so->rb_alpha_control = A5XX_RB_ALPHA_CONTROL_ALPHA_TEST | A5XX_RB_ALPHA_CONTROL_ALPHA_REF(ref) | A5XX_RB_ALPHA_CONTROL_ALPHA_TEST_FUNC(cso->alpha.func); // so->rb_depth_control |= // A5XX_RB_DEPTH_CONTROL_EARLY_Z_DISABLE; } return so; }
/** * Translate a geometry program to create a new variant. */ static struct st_gp_variant * st_translate_geometry_program(struct st_context *st, struct st_geometry_program *stgp, const struct st_gp_variant_key *key) { GLuint inputMapping[GEOM_ATTRIB_MAX]; GLuint outputMapping[GEOM_RESULT_MAX]; struct pipe_context *pipe = st->pipe; GLuint attr; GLbitfield64 inputsRead; GLuint vslot = 0; GLuint num_generic = 0; uint gs_num_inputs = 0; uint gs_builtin_inputs = 0; uint gs_array_offset = 0; ubyte gs_output_semantic_name[PIPE_MAX_SHADER_OUTPUTS]; ubyte gs_output_semantic_index[PIPE_MAX_SHADER_OUTPUTS]; uint gs_num_outputs = 0; GLint i; GLuint maxSlot = 0; struct ureg_program *ureg; struct st_gp_variant *gpv; gpv = CALLOC_STRUCT(st_gp_variant); if (!gpv) return NULL; _mesa_remove_output_reads(&stgp->Base.Base, PROGRAM_OUTPUT); _mesa_remove_output_reads(&stgp->Base.Base, PROGRAM_VARYING); ureg = ureg_create( TGSI_PROCESSOR_GEOMETRY ); if (ureg == NULL) { free(gpv); return NULL; } /* which vertex output goes to the first geometry input */ vslot = 0; memset(inputMapping, 0, sizeof(inputMapping)); memset(outputMapping, 0, sizeof(outputMapping)); /* * Convert Mesa program inputs to TGSI input register semantics. */ inputsRead = stgp->Base.Base.InputsRead; for (attr = 0; attr < GEOM_ATTRIB_MAX; attr++) { if ((inputsRead & BITFIELD64_BIT(attr)) != 0) { const GLuint slot = gs_num_inputs; gs_num_inputs++; inputMapping[attr] = slot; stgp->input_map[slot + gs_array_offset] = vslot - gs_builtin_inputs; stgp->input_to_index[attr] = vslot; stgp->index_to_input[vslot] = attr; ++vslot; if (attr != GEOM_ATTRIB_PRIMITIVE_ID) { gs_array_offset += 2; } else ++gs_builtin_inputs; #if 0 debug_printf("input map at %d = %d\n", slot + gs_array_offset, stgp->input_map[slot + gs_array_offset]); #endif switch (attr) { case GEOM_ATTRIB_PRIMITIVE_ID: stgp->input_semantic_name[slot] = TGSI_SEMANTIC_PRIMID; stgp->input_semantic_index[slot] = 0; break; case GEOM_ATTRIB_POSITION: stgp->input_semantic_name[slot] = TGSI_SEMANTIC_POSITION; stgp->input_semantic_index[slot] = 0; break; case GEOM_ATTRIB_COLOR0: stgp->input_semantic_name[slot] = TGSI_SEMANTIC_COLOR; stgp->input_semantic_index[slot] = 0; break; case GEOM_ATTRIB_COLOR1: stgp->input_semantic_name[slot] = TGSI_SEMANTIC_COLOR; stgp->input_semantic_index[slot] = 1; break; case GEOM_ATTRIB_FOG_FRAG_COORD: stgp->input_semantic_name[slot] = TGSI_SEMANTIC_FOG; stgp->input_semantic_index[slot] = 0; break; case GEOM_ATTRIB_TEX_COORD: stgp->input_semantic_name[slot] = TGSI_SEMANTIC_GENERIC; stgp->input_semantic_index[slot] = num_generic++; break; case GEOM_ATTRIB_VAR0: /* fall-through */ default: stgp->input_semantic_name[slot] = TGSI_SEMANTIC_GENERIC; stgp->input_semantic_index[slot] = num_generic++; } } } /* initialize output semantics to defaults */ for (i = 0; i < PIPE_MAX_SHADER_OUTPUTS; i++) { gs_output_semantic_name[i] = TGSI_SEMANTIC_GENERIC; gs_output_semantic_index[i] = 0; } num_generic = 0; /* * Determine number of outputs, the (default) output register * mapping and the semantic information for each output. */ for (attr = 0; attr < GEOM_RESULT_MAX; attr++) { if (stgp->Base.Base.OutputsWritten & BITFIELD64_BIT(attr)) { GLuint slot; slot = gs_num_outputs; gs_num_outputs++; outputMapping[attr] = slot; switch (attr) { case GEOM_RESULT_POS: assert(slot == 0); gs_output_semantic_name[slot] = TGSI_SEMANTIC_POSITION; gs_output_semantic_index[slot] = 0; break; case GEOM_RESULT_COL0: gs_output_semantic_name[slot] = TGSI_SEMANTIC_COLOR; gs_output_semantic_index[slot] = 0; break; case GEOM_RESULT_COL1: gs_output_semantic_name[slot] = TGSI_SEMANTIC_COLOR; gs_output_semantic_index[slot] = 1; break; case GEOM_RESULT_SCOL0: gs_output_semantic_name[slot] = TGSI_SEMANTIC_BCOLOR; gs_output_semantic_index[slot] = 0; break; case GEOM_RESULT_SCOL1: gs_output_semantic_name[slot] = TGSI_SEMANTIC_BCOLOR; gs_output_semantic_index[slot] = 1; break; case GEOM_RESULT_FOGC: gs_output_semantic_name[slot] = TGSI_SEMANTIC_FOG; gs_output_semantic_index[slot] = 0; break; case GEOM_RESULT_PSIZ: gs_output_semantic_name[slot] = TGSI_SEMANTIC_PSIZE; gs_output_semantic_index[slot] = 0; break; case GEOM_RESULT_TEX0: case GEOM_RESULT_TEX1: case GEOM_RESULT_TEX2: case GEOM_RESULT_TEX3: case GEOM_RESULT_TEX4: case GEOM_RESULT_TEX5: case GEOM_RESULT_TEX6: case GEOM_RESULT_TEX7: /* fall-through */ case GEOM_RESULT_VAR0: /* fall-through */ default: assert(slot < Elements(gs_output_semantic_name)); /* use default semantic info */ gs_output_semantic_name[slot] = TGSI_SEMANTIC_GENERIC; gs_output_semantic_index[slot] = num_generic++; } } } assert(gs_output_semantic_name[0] == TGSI_SEMANTIC_POSITION); /* find max output slot referenced to compute gs_num_outputs */ for (attr = 0; attr < GEOM_RESULT_MAX; attr++) { if (outputMapping[attr] != ~0 && outputMapping[attr] > maxSlot) maxSlot = outputMapping[attr]; } gs_num_outputs = maxSlot + 1; #if 0 /* debug */ { GLuint i; printf("outputMapping? %d\n", outputMapping ? 1 : 0); if (outputMapping) { printf("attr -> slot\n"); for (i = 0; i < 16; i++) { printf(" %2d %3d\n", i, outputMapping[i]); } } printf("slot sem_name sem_index\n"); for (i = 0; i < gs_num_outputs; i++) { printf(" %2d %d %d\n", i, gs_output_semantic_name[i], gs_output_semantic_index[i]); } } #endif /* free old shader state, if any */ if (stgp->tgsi.tokens) { st_free_tokens(stgp->tgsi.tokens); stgp->tgsi.tokens = NULL; } ureg_property_gs_input_prim(ureg, stgp->Base.InputType); ureg_property_gs_output_prim(ureg, stgp->Base.OutputType); ureg_property_gs_max_vertices(ureg, stgp->Base.VerticesOut); st_translate_mesa_program(st->ctx, TGSI_PROCESSOR_GEOMETRY, ureg, &stgp->Base.Base, /* inputs */ gs_num_inputs, inputMapping, stgp->input_semantic_name, stgp->input_semantic_index, NULL, /* outputs */ gs_num_outputs, outputMapping, gs_output_semantic_name, gs_output_semantic_index, FALSE, FALSE); stgp->num_inputs = gs_num_inputs; stgp->tgsi.tokens = ureg_get_tokens( ureg, NULL ); ureg_destroy( ureg ); if (stgp->glsl_to_tgsi) { st_translate_stream_output_info(stgp->glsl_to_tgsi, outputMapping, &stgp->tgsi.stream_output); } /* fill in new variant */ gpv->driver_shader = pipe->create_gs_state(pipe, &stgp->tgsi); gpv->key = *key; if ((ST_DEBUG & DEBUG_TGSI) && (ST_DEBUG & DEBUG_MESA)) { _mesa_print_program(&stgp->Base.Base); debug_printf("\n"); } if (ST_DEBUG & DEBUG_TGSI) { tgsi_dump(stgp->tgsi.tokens, 0); debug_printf("\n"); } return gpv; }
struct nouveau_screen * nv30_screen_create(struct nouveau_device *dev) { struct nv30_screen *screen; struct pipe_screen *pscreen; struct nouveau_pushbuf *push; struct nv04_fifo *fifo; unsigned oclass = 0; int ret, i; switch (dev->chipset & 0xf0) { case 0x30: if (RANKINE_0397_CHIPSET & (1 << (dev->chipset & 0x0f))) oclass = NV30_3D_CLASS; else if (RANKINE_0697_CHIPSET & (1 << (dev->chipset & 0x0f))) oclass = NV34_3D_CLASS; else if (RANKINE_0497_CHIPSET & (1 << (dev->chipset & 0x0f))) oclass = NV35_3D_CLASS; break; case 0x40: if (CURIE_4097_CHIPSET & (1 << (dev->chipset & 0x0f))) oclass = NV40_3D_CLASS; else if (CURIE_4497_CHIPSET & (1 << (dev->chipset & 0x0f))) oclass = NV44_3D_CLASS; break; case 0x60: if (CURIE_4497_CHIPSET6X & (1 << (dev->chipset & 0x0f))) oclass = NV44_3D_CLASS; break; default: break; } if (!oclass) { NOUVEAU_ERR("unknown 3d class for 0x%02x\n", dev->chipset); return NULL; } screen = CALLOC_STRUCT(nv30_screen); if (!screen) return NULL; pscreen = &screen->base.base; pscreen->destroy = nv30_screen_destroy; /* * Some modern apps try to use msaa without keeping in mind the * restrictions on videomem of older cards. Resulting in dmesg saying: * [ 1197.850642] nouveau E[soffice.bin[3785]] fail ttm_validate * [ 1197.850648] nouveau E[soffice.bin[3785]] validating bo list * [ 1197.850654] nouveau E[soffice.bin[3785]] validate: -12 * * Because we are running out of video memory, after which the program * using the msaa visual freezes, and eventually the entire system freezes. * * To work around this we do not allow msaa visauls by default and allow * the user to override this via NV30_MAX_MSAA. */ screen->max_sample_count = debug_get_num_option("NV30_MAX_MSAA", 0); if (screen->max_sample_count > 4) screen->max_sample_count = 4; pscreen->get_param = nv30_screen_get_param; pscreen->get_paramf = nv30_screen_get_paramf; pscreen->get_shader_param = nv30_screen_get_shader_param; pscreen->context_create = nv30_context_create; pscreen->is_format_supported = nv30_screen_is_format_supported; nv30_resource_screen_init(pscreen); nouveau_screen_init_vdec(&screen->base); screen->base.fence.emit = nv30_screen_fence_emit; screen->base.fence.update = nv30_screen_fence_update; ret = nouveau_screen_init(&screen->base, dev); if (ret) FAIL_SCREEN_INIT("nv30_screen_init failed: %d\n", ret); screen->base.vidmem_bindings |= PIPE_BIND_VERTEX_BUFFER; screen->base.sysmem_bindings |= PIPE_BIND_VERTEX_BUFFER; if (oclass == NV40_3D_CLASS) { screen->base.vidmem_bindings |= PIPE_BIND_INDEX_BUFFER; screen->base.sysmem_bindings |= PIPE_BIND_INDEX_BUFFER; } fifo = screen->base.channel->data; push = screen->base.pushbuf; push->rsvd_kick = 16; ret = nouveau_object_new(screen->base.channel, 0x00000000, NV01_NULL_CLASS, NULL, 0, &screen->null); if (ret) FAIL_SCREEN_INIT("error allocating null object: %d\n", ret); /* DMA_FENCE refuses to accept DMA objects with "adjust" filled in, * this means that the address pointed at by the DMA object must * be 4KiB aligned, which means this object needs to be the first * one allocated on the channel. */ ret = nouveau_object_new(screen->base.channel, 0xbeef1e00, NOUVEAU_NOTIFIER_CLASS, &(struct nv04_notify) { .length = 32 }, sizeof(struct nv04_notify),
/** * Create a new pipe_screen object * Note: we're not presently subclassing pipe_screen (no llvmpipe_screen). */ struct pipe_screen * llvmpipe_create_screen(struct sw_winsys *winsys) { struct llvmpipe_screen *screen; util_cpu_detect(); #ifdef DEBUG LP_DEBUG = debug_get_flags_option("LP_DEBUG", lp_debug_flags, 0 ); #endif LP_PERF = debug_get_flags_option("LP_PERF", lp_perf_flags, 0 ); screen = CALLOC_STRUCT(llvmpipe_screen); if (!screen) return NULL; if (!lp_jit_screen_init(screen)) { FREE(screen); return NULL; } screen->winsys = winsys; screen->base.destroy = llvmpipe_destroy_screen; screen->base.get_name = llvmpipe_get_name; screen->base.get_vendor = llvmpipe_get_vendor; screen->base.get_device_vendor = llvmpipe_get_vendor; // TODO should be the CPU vendor screen->base.get_param = llvmpipe_get_param; screen->base.get_shader_param = llvmpipe_get_shader_param; screen->base.get_paramf = llvmpipe_get_paramf; screen->base.is_format_supported = llvmpipe_is_format_supported; screen->base.context_create = llvmpipe_create_context; screen->base.flush_frontbuffer = llvmpipe_flush_frontbuffer; screen->base.fence_reference = llvmpipe_fence_reference; screen->base.fence_finish = llvmpipe_fence_finish; screen->base.get_timestamp = llvmpipe_get_timestamp; llvmpipe_init_screen_resource_funcs(&screen->base); screen->num_threads = util_cpu_caps.nr_cpus > 1 ? util_cpu_caps.nr_cpus : 0; #ifdef PIPE_SUBSYSTEM_EMBEDDED screen->num_threads = 0; #endif screen->num_threads = debug_get_num_option("LP_NUM_THREADS", screen->num_threads); screen->num_threads = MIN2(screen->num_threads, LP_MAX_THREADS); screen->rast = lp_rast_create(screen->num_threads); if (!screen->rast) { lp_jit_screen_cleanup(screen); FREE(screen); return NULL; } pipe_mutex_init(screen->rast_mutex); util_format_s3tc_init(); return &screen->base; }
/** * Create a framebuffer from a manager interface. */ static struct st_framebuffer * st_framebuffer_create(struct st_context *st, struct st_framebuffer_iface *stfbi) { struct st_framebuffer *stfb; struct gl_config mode; gl_buffer_index idx; if (!stfbi) return NULL; stfb = CALLOC_STRUCT(st_framebuffer); if (!stfb) return NULL; st_visual_to_context_mode(stfbi->visual, &mode); /* * For desktop GL, sRGB framebuffer write is controlled by both the * capability of the framebuffer and GL_FRAMEBUFFER_SRGB. We should * advertise the capability when the pipe driver (and core Mesa) supports * it so that applications can enable sRGB write when they want to. * * This is not to be confused with GLX_FRAMEBUFFER_SRGB_CAPABLE_ARB. When * the attribute is GLX_TRUE, it tells the st manager to pick a color * format such that util_format_srgb(visual->color_format) can be supported * by the pipe driver. We still need to advertise the capability here. * * For GLES, however, sRGB framebuffer write is controlled only by the * capability of the framebuffer. There is GL_EXT_sRGB_write_control to * give applications the control back, but sRGB write is still enabled by * default. To avoid unexpected results, we should not advertise the * capability. This could change when we add support for * EGL_KHR_gl_colorspace. */ if (_mesa_is_desktop_gl(st->ctx)) { struct pipe_screen *screen = st->pipe->screen; const enum pipe_format srgb_format = util_format_srgb(stfbi->visual->color_format); if (srgb_format != PIPE_FORMAT_NONE && st_pipe_format_to_mesa_format(srgb_format) != MESA_FORMAT_NONE && screen->is_format_supported(screen, srgb_format, PIPE_TEXTURE_2D, stfbi->visual->samples, PIPE_BIND_RENDER_TARGET)) mode.sRGBCapable = GL_TRUE; } _mesa_initialize_window_framebuffer(&stfb->Base, &mode); stfb->iface = stfbi; stfb->iface_stamp = p_atomic_read(&stfbi->stamp) - 1; /* add the color buffer */ idx = stfb->Base._ColorDrawBufferIndexes[0]; if (!st_framebuffer_add_renderbuffer(stfb, idx)) { free(stfb); return NULL; } st_framebuffer_add_renderbuffer(stfb, BUFFER_DEPTH); st_framebuffer_add_renderbuffer(stfb, BUFFER_ACCUM); stfb->stamp = 0; st_framebuffer_update_attachments(stfb); return stfb; }
svga_texture_destroy, /* resource_destroy */ svga_texture_get_transfer, /* get_transfer */ svga_texture_transfer_destroy, /* transfer_destroy */ svga_texture_transfer_map, /* transfer_map */ u_default_transfer_flush_region, /* transfer_flush_region */ svga_texture_transfer_unmap, /* transfer_unmap */ u_default_transfer_inline_write /* transfer_inline_write */ }; struct pipe_resource * svga_texture_create(struct pipe_screen *screen, const struct pipe_resource *template) { struct svga_screen *svgascreen = svga_screen(screen); struct svga_texture *tex = CALLOC_STRUCT(svga_texture); if (!tex) goto error1; tex->b.b = *template; tex->b.vtbl = &svga_texture_vtbl; pipe_reference_init(&tex->b.b.reference, 1); tex->b.b.screen = screen; assert(template->last_level < SVGA_MAX_TEXTURE_LEVELS); if(template->last_level >= SVGA_MAX_TEXTURE_LEVELS) goto error2; tex->key.flags = 0; tex->key.size.width = template->width0;
struct blitter_context *util_blitter_create(struct pipe_context *pipe) { struct blitter_context_priv *ctx; struct pipe_blend_state blend; struct pipe_depth_stencil_alpha_state dsa; struct pipe_rasterizer_state rs_state; struct pipe_sampler_state sampler_state; struct pipe_vertex_element velem[2]; unsigned i; ctx = CALLOC_STRUCT(blitter_context_priv); if (!ctx) return NULL; ctx->base.pipe = pipe; ctx->base.draw_rectangle = blitter_draw_rectangle; /* init state objects for them to be considered invalid */ ctx->base.saved_blend_state = INVALID_PTR; ctx->base.saved_dsa_state = INVALID_PTR; ctx->base.saved_rs_state = INVALID_PTR; ctx->base.saved_fs = INVALID_PTR; ctx->base.saved_vs = INVALID_PTR; ctx->base.saved_gs = INVALID_PTR; ctx->base.saved_velem_state = INVALID_PTR; ctx->base.saved_fb_state.nr_cbufs = ~0; ctx->base.saved_num_sampler_views = ~0; ctx->base.saved_num_sampler_states = ~0; ctx->base.saved_num_vertex_buffers = ~0; ctx->base.saved_num_so_targets = ~0; ctx->has_geometry_shader = pipe->screen->get_shader_param(pipe->screen, PIPE_SHADER_GEOMETRY, PIPE_SHADER_CAP_MAX_INSTRUCTIONS) > 0; ctx->vertex_has_integers = pipe->screen->get_shader_param(pipe->screen, PIPE_SHADER_VERTEX, PIPE_SHADER_CAP_INTEGERS); ctx->has_stream_out = pipe->screen->get_param(pipe->screen, PIPE_CAP_MAX_STREAM_OUTPUT_BUFFERS) != 0; /* blend state objects */ memset(&blend, 0, sizeof(blend)); ctx->blend_keep_color = pipe->create_blend_state(pipe, &blend); blend.rt[0].colormask = PIPE_MASK_RGBA; ctx->blend_write_color = pipe->create_blend_state(pipe, &blend); /* depth stencil alpha state objects */ memset(&dsa, 0, sizeof(dsa)); ctx->dsa_keep_depth_stencil = pipe->create_depth_stencil_alpha_state(pipe, &dsa); dsa.depth.enabled = 1; dsa.depth.writemask = 1; dsa.depth.func = PIPE_FUNC_ALWAYS; ctx->dsa_write_depth_keep_stencil = pipe->create_depth_stencil_alpha_state(pipe, &dsa); dsa.stencil[0].enabled = 1; dsa.stencil[0].func = PIPE_FUNC_ALWAYS; dsa.stencil[0].fail_op = PIPE_STENCIL_OP_REPLACE; dsa.stencil[0].zpass_op = PIPE_STENCIL_OP_REPLACE; dsa.stencil[0].zfail_op = PIPE_STENCIL_OP_REPLACE; dsa.stencil[0].valuemask = 0xff; dsa.stencil[0].writemask = 0xff; ctx->dsa_write_depth_stencil = pipe->create_depth_stencil_alpha_state(pipe, &dsa); dsa.depth.enabled = 0; dsa.depth.writemask = 0; ctx->dsa_keep_depth_write_stencil = pipe->create_depth_stencil_alpha_state(pipe, &dsa); /* sampler state */ memset(&sampler_state, 0, sizeof(sampler_state)); sampler_state.wrap_s = PIPE_TEX_WRAP_CLAMP_TO_EDGE; sampler_state.wrap_t = PIPE_TEX_WRAP_CLAMP_TO_EDGE; sampler_state.wrap_r = PIPE_TEX_WRAP_CLAMP_TO_EDGE; sampler_state.normalized_coords = 1; ctx->sampler_state = pipe->create_sampler_state(pipe, &sampler_state); /* rasterizer state */ memset(&rs_state, 0, sizeof(rs_state)); rs_state.cull_face = PIPE_FACE_NONE; rs_state.gl_rasterization_rules = 1; rs_state.flatshade = 1; rs_state.depth_clip = 1; ctx->rs_state = pipe->create_rasterizer_state(pipe, &rs_state); if (ctx->has_stream_out) { rs_state.rasterizer_discard = 1; ctx->rs_discard_state = pipe->create_rasterizer_state(pipe, &rs_state); } /* vertex elements states */ memset(&velem[0], 0, sizeof(velem[0]) * 2); for (i = 0; i < 2; i++) { velem[i].src_offset = i * 4 * sizeof(float); velem[i].src_format = PIPE_FORMAT_R32G32B32A32_FLOAT; } ctx->velem_state = pipe->create_vertex_elements_state(pipe, 2, &velem[0]); if (ctx->vertex_has_integers) { memset(&velem[0], 0, sizeof(velem[0]) * 2); velem[0].src_offset = 0; velem[0].src_format = PIPE_FORMAT_R32G32B32A32_FLOAT; velem[1].src_offset = 4 * sizeof(float); velem[1].src_format = PIPE_FORMAT_R32G32B32A32_SINT; ctx->velem_sint_state = pipe->create_vertex_elements_state(pipe, 2, &velem[0]); memset(&velem[0], 0, sizeof(velem[0]) * 2); velem[0].src_offset = 0; velem[0].src_format = PIPE_FORMAT_R32G32B32A32_FLOAT; velem[1].src_offset = 4 * sizeof(float); velem[1].src_format = PIPE_FORMAT_R32G32B32A32_UINT; ctx->velem_uint_state = pipe->create_vertex_elements_state(pipe, 2, &velem[0]); } if (ctx->has_stream_out) { velem[0].src_format = PIPE_FORMAT_R32G32B32A32_FLOAT; ctx->velem_state_readbuf = pipe->create_vertex_elements_state(pipe, 1, &velem[0]); } /* fragment shaders are created on-demand */ /* vertex shaders */ { const uint semantic_names[] = { TGSI_SEMANTIC_POSITION, TGSI_SEMANTIC_GENERIC }; const uint semantic_indices[] = { 0, 0 }; ctx->vs = util_make_vertex_passthrough_shader(pipe, 2, semantic_names, semantic_indices); } if (ctx->has_stream_out) { struct pipe_stream_output_info so; const uint semantic_names[] = { TGSI_SEMANTIC_POSITION }; const uint semantic_indices[] = { 0 }; memset(&so, 0, sizeof(so)); so.num_outputs = 1; so.output[0].register_mask = TGSI_WRITEMASK_XYZW; so.stride = 4; ctx->vs_pos_only = util_make_vertex_passthrough_shader_with_so(pipe, 1, semantic_names, semantic_indices, &so); } /* set invariant vertex coordinates */ for (i = 0; i < 4; i++) ctx->vertices[i][0][3] = 1; /*v.w*/ /* create the vertex buffer */ ctx->vbuf = pipe_user_buffer_create(ctx->base.pipe->screen, ctx->vertices, sizeof(ctx->vertices), PIPE_BIND_VERTEX_BUFFER); return &ctx->base; }
static void *si_texture_transfer_map(struct pipe_context *ctx, struct pipe_resource *texture, unsigned level, unsigned usage, const struct pipe_box *box, struct pipe_transfer **ptransfer) { struct r600_context *rctx = (struct r600_context *)ctx; struct r600_resource_texture *rtex = (struct r600_resource_texture*)texture; struct pipe_resource resource; struct r600_transfer *trans; int r; boolean use_staging_texture = FALSE; struct radeon_winsys_cs_handle *buf; enum pipe_format format = texture->format; unsigned offset = 0; char *map; /* We cannot map a tiled texture directly because the data is * in a different order, therefore we do detiling using a blit. * * Also, use a temporary in GTT memory for read transfers, as * the CPU is much happier reading out of cached system memory * than uncached VRAM. */ if (rtex->surface.level[level].mode != RADEON_SURF_MODE_LINEAR_ALIGNED && rtex->surface.level[level].mode != RADEON_SURF_MODE_LINEAR) use_staging_texture = TRUE; /* XXX: Use a staging texture for uploads if the underlying BO * is busy. No interface for checking that currently? so do * it eagerly whenever the transfer doesn't require a readback * and might block. */ if ((usage & PIPE_TRANSFER_WRITE) && !(usage & (PIPE_TRANSFER_READ | PIPE_TRANSFER_DONTBLOCK | PIPE_TRANSFER_UNSYNCHRONIZED))) use_staging_texture = TRUE; if (!permit_hardware_blit(ctx->screen, texture) || (texture->flags & R600_RESOURCE_FLAG_TRANSFER)) use_staging_texture = FALSE; if (use_staging_texture && (usage & PIPE_TRANSFER_MAP_DIRECTLY)) return NULL; trans = CALLOC_STRUCT(r600_transfer); if (trans == NULL) return NULL; pipe_resource_reference(&trans->transfer.resource, texture); trans->transfer.level = level; trans->transfer.usage = usage; trans->transfer.box = *box; if (rtex->depth) { /* XXX: only readback the rectangle which is being mapped? */ /* XXX: when discard is true, no need to read back from depth texture */ r = r600_texture_depth_flush(ctx, texture, FALSE); if (r < 0) { R600_ERR("failed to create temporary texture to hold untiled copy\n"); pipe_resource_reference(&trans->transfer.resource, NULL); FREE(trans); return NULL; } trans->transfer.stride = rtex->flushed_depth_texture->surface.level[level].pitch_bytes; trans->offset = r600_texture_get_offset(rtex->flushed_depth_texture, level, box->z); } else if (use_staging_texture) { resource.target = PIPE_TEXTURE_2D; resource.format = texture->format; resource.width0 = box->width; resource.height0 = box->height; resource.depth0 = 1; resource.array_size = 1; resource.last_level = 0; resource.nr_samples = 0; resource.usage = PIPE_USAGE_STAGING; resource.bind = 0; resource.flags = R600_RESOURCE_FLAG_TRANSFER; /* For texture reading, the temporary (detiled) texture is used as * a render target when blitting from a tiled texture. */ if (usage & PIPE_TRANSFER_READ) { resource.bind |= PIPE_BIND_RENDER_TARGET; } /* For texture writing, the temporary texture is used as a sampler * when blitting into a tiled texture. */ if (usage & PIPE_TRANSFER_WRITE) { resource.bind |= PIPE_BIND_SAMPLER_VIEW; } /* Create the temporary texture. */ trans->staging_texture = ctx->screen->resource_create(ctx->screen, &resource); if (trans->staging_texture == NULL) { R600_ERR("failed to create temporary texture to hold untiled copy\n"); pipe_resource_reference(&trans->transfer.resource, NULL); FREE(trans); return NULL; } trans->transfer.stride = ((struct r600_resource_texture *)trans->staging_texture) ->surface.level[0].pitch_bytes; if (usage & PIPE_TRANSFER_READ) { r600_copy_to_staging_texture(ctx, trans); /* Always referenced in the blit. */ radeonsi_flush(ctx, NULL, 0); } } else { trans->transfer.stride = rtex->surface.level[level].pitch_bytes; trans->transfer.layer_stride = rtex->surface.level[level].slice_size; trans->offset = r600_texture_get_offset(rtex, level, box->z); } if (trans->staging_texture) { buf = si_resource(trans->staging_texture)->cs_buf; } else { struct r600_resource_texture *rtex = (struct r600_resource_texture*)texture; if (rtex->flushed_depth_texture) buf = rtex->flushed_depth_texture->resource.cs_buf; else buf = si_resource(texture)->cs_buf; offset = trans->offset + box->y / util_format_get_blockheight(format) * trans->transfer.stride + box->x / util_format_get_blockwidth(format) * util_format_get_blocksize(format); } if (!(map = rctx->ws->buffer_map(buf, rctx->cs, usage))) { pipe_resource_reference(&trans->staging_texture, NULL); pipe_resource_reference(&trans->transfer.resource, NULL); FREE(trans); return NULL; } *ptransfer = &trans->transfer; return map + offset; }
struct pipe_screen * nv50_screen_create(struct nouveau_device *dev) { struct nv50_screen *screen; struct pipe_screen *pscreen; struct nouveau_object *chan; uint64_t value; uint32_t tesla_class; unsigned stack_size; int ret; screen = CALLOC_STRUCT(nv50_screen); if (!screen) return NULL; pscreen = &screen->base.base; ret = nouveau_screen_init(&screen->base, dev); if (ret) { NOUVEAU_ERR("nouveau_screen_init failed: %d\n", ret); goto fail; } /* TODO: Prevent FIFO prefetch before transfer of index buffers and * admit them to VRAM. */ screen->base.vidmem_bindings |= PIPE_BIND_CONSTANT_BUFFER | PIPE_BIND_VERTEX_BUFFER; screen->base.sysmem_bindings |= PIPE_BIND_VERTEX_BUFFER | PIPE_BIND_INDEX_BUFFER; screen->base.pushbuf->user_priv = screen; screen->base.pushbuf->rsvd_kick = 5; chan = screen->base.channel; pscreen->destroy = nv50_screen_destroy; pscreen->context_create = nv50_create; pscreen->is_format_supported = nv50_screen_is_format_supported; pscreen->get_param = nv50_screen_get_param; pscreen->get_shader_param = nv50_screen_get_shader_param; pscreen->get_paramf = nv50_screen_get_paramf; nv50_screen_init_resource_functions(pscreen); if (screen->base.device->chipset < 0x84 || debug_get_bool_option("NOUVEAU_PMPEG", FALSE)) { /* PMPEG */ nouveau_screen_init_vdec(&screen->base); } else if (screen->base.device->chipset < 0x98 || screen->base.device->chipset == 0xa0) { /* VP2 */ screen->base.base.get_video_param = nv84_screen_get_video_param; screen->base.base.is_video_format_supported = nv84_screen_video_supported; } else { /* VP3/4 */ screen->base.base.get_video_param = nouveau_vp3_screen_get_video_param; screen->base.base.is_video_format_supported = nouveau_vp3_screen_video_supported; } ret = nouveau_bo_new(dev, NOUVEAU_BO_GART | NOUVEAU_BO_MAP, 0, 4096, NULL, &screen->fence.bo); if (ret) { NOUVEAU_ERR("Failed to allocate fence bo: %d\n", ret); goto fail; } nouveau_bo_map(screen->fence.bo, 0, NULL); screen->fence.map = screen->fence.bo->map; screen->base.fence.emit = nv50_screen_fence_emit; screen->base.fence.update = nv50_screen_fence_update; ret = nouveau_object_new(chan, 0xbeef0301, NOUVEAU_NOTIFIER_CLASS, &(struct nv04_notify){ .length = 32 }, sizeof(struct nv04_notify), &screen->sync);
struct pipe_context *svga_context_create( struct pipe_screen *screen, void *priv ) { struct svga_screen *svgascreen = svga_screen(screen); struct svga_context *svga = NULL; enum pipe_error ret; svga = CALLOC_STRUCT(svga_context); if (svga == NULL) goto no_svga; svga->pipe.screen = screen; svga->pipe.priv = priv; svga->pipe.destroy = svga_destroy; svga->pipe.clear = svga_clear; svga->swc = svgascreen->sws->context_create(svgascreen->sws); if(!svga->swc) goto no_swc; svga_init_resource_functions(svga); svga_init_blend_functions(svga); svga_init_blit_functions(svga); svga_init_depth_stencil_functions(svga); svga_init_draw_functions(svga); svga_init_flush_functions(svga); svga_init_misc_functions(svga); svga_init_rasterizer_functions(svga); svga_init_sampler_functions(svga); svga_init_fs_functions(svga); svga_init_vs_functions(svga); svga_init_vertex_functions(svga); svga_init_constbuffer_functions(svga); svga_init_query_functions(svga); svga_init_surface_functions(svga); /* debug */ svga->debug.no_swtnl = debug_get_option_no_swtnl(); svga->debug.force_swtnl = debug_get_option_force_swtnl(); svga->debug.use_min_mipmap = debug_get_option_use_min_mipmap(); svga->debug.disable_shader = debug_get_option_disable_shader(); svga->debug.no_line_width = debug_get_option_no_line_width(); svga->debug.force_hw_line_stipple = debug_get_option_force_hw_line_stipple(); svga->fs_bm = util_bitmask_create(); if (svga->fs_bm == NULL) goto no_fs_bm; svga->vs_bm = util_bitmask_create(); if (svga->vs_bm == NULL) goto no_vs_bm; svga->hwtnl = svga_hwtnl_create(svga); if (svga->hwtnl == NULL) goto no_hwtnl; if (!svga_init_swtnl(svga)) goto no_swtnl; ret = svga_emit_initial_state( svga ); if (ret != PIPE_OK) goto no_state; /* Avoid shortcircuiting state with initial value of zero. */ memset(&svga->state.hw_clear, 0xcd, sizeof(svga->state.hw_clear)); memset(&svga->state.hw_clear.framebuffer, 0x0, sizeof(svga->state.hw_clear.framebuffer)); memset(&svga->state.hw_draw, 0xcd, sizeof(svga->state.hw_draw)); memset(&svga->state.hw_draw.views, 0x0, sizeof(svga->state.hw_draw.views)); svga->state.hw_draw.num_views = 0; svga->dirty = ~0; LIST_INITHEAD(&svga->dirty_buffers); return &svga->pipe; no_state: svga_destroy_swtnl(svga); no_swtnl: svga_hwtnl_destroy( svga->hwtnl ); no_hwtnl: util_bitmask_destroy( svga->vs_bm ); no_vs_bm: util_bitmask_destroy( svga->fs_bm ); no_fs_bm: svga->swc->destroy(svga->swc); no_swc: FREE(svga); no_svga: return NULL; }
/** * Create a new stw_framebuffer object which corresponds to the given * HDC/window. If successful, we return the new stw_framebuffer object * with its mutex locked. */ struct stw_framebuffer * stw_framebuffer_create(HDC hdc, int iPixelFormat) { HWND hWnd; struct stw_framebuffer *fb; const struct stw_pixelformat_info *pfi; /* We only support drawing to a window. */ hWnd = WindowFromDC( hdc ); if (!hWnd) return NULL; fb = CALLOC_STRUCT( stw_framebuffer ); if (fb == NULL) return NULL; fb->hWnd = hWnd; fb->iPixelFormat = iPixelFormat; /* * We often need a displayable pixel format to make GDI happy. Set it * here (always 1, i.e., out first pixel format) where appropriate. */ fb->iDisplayablePixelFormat = iPixelFormat <= stw_dev->pixelformat_count ? iPixelFormat : 1; fb->pfi = pfi = stw_pixelformat_get_info( iPixelFormat ); fb->stfb = stw_st_create_framebuffer( fb ); if (!fb->stfb) { FREE( fb ); return NULL; } fb->refcnt = 1; /* * Windows can be sometimes have zero width and or height, but we ensure * a non-zero framebuffer size at all times. */ fb->must_resize = TRUE; fb->width = 1; fb->height = 1; fb->client_rect.left = 0; fb->client_rect.top = 0; fb->client_rect.right = fb->client_rect.left + fb->width; fb->client_rect.bottom = fb->client_rect.top + fb->height; stw_framebuffer_get_size(fb); InitializeCriticalSection(&fb->mutex); /* This is the only case where we lock the stw_framebuffer::mutex before * stw_dev::fb_mutex, since no other thread can know about this framebuffer * and we must prevent any other thread from destroying it before we return. */ stw_framebuffer_lock(fb); stw_lock_framebuffers(stw_dev); fb->next = stw_dev->fb_head; stw_dev->fb_head = fb; stw_unlock_framebuffers(stw_dev); return fb; }
/* * Create a new X/Mesa visual. * Input: display - X11 display * visinfo - an XVisualInfo pointer * rgb_flag - GL_TRUE = RGB mode, * GL_FALSE = color index mode * alpha_flag - alpha buffer requested? * db_flag - GL_TRUE = double-buffered, * GL_FALSE = single buffered * stereo_flag - stereo visual? * ximage_flag - GL_TRUE = use an XImage for back buffer, * GL_FALSE = use an off-screen pixmap for back buffer * depth_size - requested bits/depth values, or zero * stencil_size - requested bits/stencil values, or zero * accum_red_size - requested bits/red accum values, or zero * accum_green_size - requested bits/green accum values, or zero * accum_blue_size - requested bits/blue accum values, or zero * accum_alpha_size - requested bits/alpha accum values, or zero * num_samples - number of samples/pixel if multisampling, or zero * level - visual level, usually 0 * visualCaveat - ala the GLX extension, usually GLX_NONE * Return; a new XMesaVisual or 0 if error. */ PUBLIC XMesaVisual XMesaCreateVisual( Display *display, XVisualInfo * visinfo, GLboolean rgb_flag, GLboolean alpha_flag, GLboolean db_flag, GLboolean stereo_flag, GLboolean ximage_flag, GLint depth_size, GLint stencil_size, GLint accum_red_size, GLint accum_green_size, GLint accum_blue_size, GLint accum_alpha_size, GLint num_samples, GLint level, GLint visualCaveat ) { XMesaDisplay xmdpy = xmesa_init_display(display); XMesaVisual v; GLint red_bits, green_bits, blue_bits, alpha_bits; if (!xmdpy) return NULL; /* For debugging only */ if (_mesa_getenv("MESA_XSYNC")) { /* This makes debugging X easier. * In your debugger, set a breakpoint on _XError to stop when an * X protocol error is generated. */ XSynchronize( display, 1 ); } v = (XMesaVisual) CALLOC_STRUCT(xmesa_visual); if (!v) { return NULL; } v->display = display; /* Save a copy of the XVisualInfo struct because the user may Xfree() * the struct but we may need some of the information contained in it * at a later time. */ v->visinfo = (XVisualInfo *) MALLOC(sizeof(*visinfo)); if (!v->visinfo) { free(v); return NULL; } memcpy(v->visinfo, visinfo, sizeof(*visinfo)); v->ximage_flag = ximage_flag; v->mesa_visual.redMask = visinfo->red_mask; v->mesa_visual.greenMask = visinfo->green_mask; v->mesa_visual.blueMask = visinfo->blue_mask; v->mesa_visual.visualID = visinfo->visualid; v->mesa_visual.screen = visinfo->screen; #if !(defined(__cplusplus) || defined(c_plusplus)) v->mesa_visual.visualType = xmesa_convert_from_x_visual_type(visinfo->class); #else v->mesa_visual.visualType = xmesa_convert_from_x_visual_type(visinfo->c_class); #endif v->mesa_visual.visualRating = visualCaveat; if (alpha_flag) v->mesa_visual.alphaBits = 8; (void) initialize_visual_and_buffer( v, NULL, rgb_flag, 0, 0 ); { const int xclass = v->mesa_visual.visualType; if (xclass == GLX_TRUE_COLOR || xclass == GLX_DIRECT_COLOR) { red_bits = _mesa_bitcount(GET_REDMASK(v)); green_bits = _mesa_bitcount(GET_GREENMASK(v)); blue_bits = _mesa_bitcount(GET_BLUEMASK(v)); } else { /* this is an approximation */ int depth; depth = v->visinfo->depth; red_bits = depth / 3; depth -= red_bits; green_bits = depth / 2; depth -= green_bits; blue_bits = depth; alpha_bits = 0; assert( red_bits + green_bits + blue_bits == v->visinfo->depth ); } alpha_bits = v->mesa_visual.alphaBits; } /* initialize visual */ { __GLcontextModes *vis = &v->mesa_visual; vis->rgbMode = GL_TRUE; vis->doubleBufferMode = db_flag; vis->stereoMode = stereo_flag; vis->redBits = red_bits; vis->greenBits = green_bits; vis->blueBits = blue_bits; vis->alphaBits = alpha_bits; vis->rgbBits = red_bits + green_bits + blue_bits; vis->indexBits = 0; vis->depthBits = depth_size; vis->stencilBits = stencil_size; vis->accumRedBits = accum_red_size; vis->accumGreenBits = accum_green_size; vis->accumBlueBits = accum_blue_size; vis->accumAlphaBits = accum_alpha_size; vis->haveAccumBuffer = accum_red_size > 0; vis->haveDepthBuffer = depth_size > 0; vis->haveStencilBuffer = stencil_size > 0; vis->numAuxBuffers = 0; vis->level = 0; vis->pixmapMode = 0; vis->sampleBuffers = 0; vis->samples = 0; } v->stvis.buffer_mask = ST_ATTACHMENT_FRONT_LEFT_MASK; if (db_flag) v->stvis.buffer_mask |= ST_ATTACHMENT_BACK_LEFT_MASK; if (stereo_flag) { v->stvis.buffer_mask |= ST_ATTACHMENT_FRONT_RIGHT_MASK; if (db_flag) v->stvis.buffer_mask |= ST_ATTACHMENT_BACK_RIGHT_MASK; } v->stvis.color_format = choose_pixel_format(v); if (v->stvis.color_format == PIPE_FORMAT_NONE) { FREE(v->visinfo); FREE(v); return NULL; } v->stvis.depth_stencil_format = choose_depth_stencil_format(xmdpy, depth_size, stencil_size); v->stvis.accum_format = (accum_red_size + accum_green_size + accum_blue_size + accum_alpha_size) ? PIPE_FORMAT_R16G16B16A16_SNORM : PIPE_FORMAT_NONE; v->stvis.samples = num_samples; v->stvis.render_buffer = ST_ATTACHMENT_INVALID; /* XXX minor hack */ v->mesa_visual.level = level; return v; }
/** * Translate a vertex program to create a new variant. */ static struct st_vp_variant * st_translate_vertex_program(struct st_context *st, struct st_vertex_program *stvp, const struct st_vp_variant_key *key) { struct st_vp_variant *vpv = CALLOC_STRUCT(st_vp_variant); struct pipe_context *pipe = st->pipe; struct ureg_program *ureg; enum pipe_error error; unsigned num_outputs; st_prepare_vertex_program(st->ctx, stvp); if (!stvp->glsl_to_tgsi) { _mesa_remove_output_reads(&stvp->Base.Base, PROGRAM_OUTPUT); _mesa_remove_output_reads(&stvp->Base.Base, PROGRAM_VARYING); } ureg = ureg_create( TGSI_PROCESSOR_VERTEX ); if (ureg == NULL) { free(vpv); return NULL; } vpv->key = *key; vpv->num_inputs = stvp->num_inputs; num_outputs = stvp->num_outputs; if (key->passthrough_edgeflags) { vpv->num_inputs++; num_outputs++; } if (ST_DEBUG & DEBUG_MESA) { _mesa_print_program(&stvp->Base.Base); _mesa_print_program_parameters(st->ctx, &stvp->Base.Base); debug_printf("\n"); } if (stvp->glsl_to_tgsi) error = st_translate_program(st->ctx, TGSI_PROCESSOR_VERTEX, ureg, stvp->glsl_to_tgsi, &stvp->Base.Base, /* inputs */ stvp->num_inputs, stvp->input_to_index, NULL, /* input semantic name */ NULL, /* input semantic index */ NULL, /* interp mode */ NULL, /* is centroid */ /* outputs */ stvp->num_outputs, stvp->result_to_output, stvp->output_semantic_name, stvp->output_semantic_index, key->passthrough_edgeflags, key->clamp_color); else error = st_translate_mesa_program(st->ctx, TGSI_PROCESSOR_VERTEX, ureg, &stvp->Base.Base, /* inputs */ vpv->num_inputs, stvp->input_to_index, NULL, /* input semantic name */ NULL, /* input semantic index */ NULL, /* outputs */ num_outputs, stvp->result_to_output, stvp->output_semantic_name, stvp->output_semantic_index, key->passthrough_edgeflags, key->clamp_color); if (error) goto fail; vpv->tgsi.tokens = ureg_get_tokens( ureg, NULL ); if (!vpv->tgsi.tokens) goto fail; ureg_destroy( ureg ); if (stvp->glsl_to_tgsi) { st_translate_stream_output_info(stvp->glsl_to_tgsi, stvp->result_to_output, &vpv->tgsi.stream_output); } vpv->driver_shader = pipe->create_vs_state(pipe, &vpv->tgsi); if (ST_DEBUG & DEBUG_TGSI) { tgsi_dump( vpv->tgsi.tokens, 0 ); debug_printf("\n"); } return vpv; fail: debug_printf("%s: failed to translate Mesa program:\n", __FUNCTION__); _mesa_print_program(&stvp->Base.Base); debug_assert(0); ureg_destroy( ureg ); return NULL; }
struct pipe_context * nvc0_create(struct pipe_screen *pscreen, void *priv) { struct nvc0_screen *screen = nvc0_screen(pscreen); struct nvc0_context *nvc0; struct pipe_context *pipe; int ret; uint32_t flags; nvc0 = CALLOC_STRUCT(nvc0_context); if (!nvc0) return NULL; pipe = &nvc0->base.pipe; if (!nvc0_blitctx_create(nvc0)) goto out_err; nvc0->base.pushbuf = screen->base.pushbuf; ret = nouveau_bufctx_new(screen->base.client, NVC0_BIND_COUNT, &nvc0->bufctx_3d); if (!ret) nouveau_bufctx_new(screen->base.client, 2, &nvc0->bufctx); if (ret) goto out_err; nvc0->screen = screen; nvc0->base.screen = &screen->base; pipe->screen = pscreen; pipe->priv = priv; pipe->destroy = nvc0_destroy; pipe->draw_vbo = nvc0_draw_vbo; pipe->clear = nvc0_clear; pipe->flush = nvc0_flush; pipe->texture_barrier = nvc0_texture_barrier; if (!screen->cur_ctx) { screen->cur_ctx = nvc0; nouveau_pushbuf_bufctx(screen->base.pushbuf, nvc0->bufctx); } screen->base.pushbuf->kick_notify = nvc0_default_kick_notify; nvc0_init_query_functions(nvc0); nvc0_init_surface_functions(nvc0); nvc0_init_state_functions(nvc0); nvc0_init_transfer_functions(nvc0); nvc0_init_resource_functions(pipe); #ifdef NVC0_WITH_DRAW_MODULE /* no software fallbacks implemented */ nvc0->draw = draw_create(pipe); assert(nvc0->draw); draw_set_rasterize_stage(nvc0->draw, nvc0_draw_render_stage(nvc0)); #endif nouveau_context_init_vdec(&nvc0->base); /* shader builtin library is per-screen, but we need a context for m2mf */ nvc0_program_library_upload(nvc0); /* add permanently resident buffers to bufctxts */ flags = NOUVEAU_BO_VRAM | NOUVEAU_BO_RD; BCTX_REFN_bo(nvc0->bufctx_3d, SCREEN, flags, screen->text); BCTX_REFN_bo(nvc0->bufctx_3d, SCREEN, flags, screen->uniform_bo); BCTX_REFN_bo(nvc0->bufctx_3d, SCREEN, flags, screen->txc); BCTX_REFN_bo(nvc0->bufctx_3d, SCREEN, flags, screen->poly_cache); flags = NOUVEAU_BO_GART | NOUVEAU_BO_WR; BCTX_REFN_bo(nvc0->bufctx_3d, SCREEN, flags, screen->fence.bo); BCTX_REFN_bo(nvc0->bufctx, FENCE, flags, screen->fence.bo); nvc0->base.scratch.bo_size = 2 << 20; memset(nvc0->tex_handles, ~0, sizeof(nvc0->tex_handles)); return pipe; out_err: if (nvc0) { if (nvc0->bufctx_3d) nouveau_bufctx_del(&nvc0->bufctx_3d); if (nvc0->bufctx) nouveau_bufctx_del(&nvc0->bufctx); if (nvc0->blit) FREE(nvc0->blit); FREE(nvc0); } return NULL; }
/** * Translate a Mesa fragment shader into a TGSI shader using extra info in * the key. * \return new fragment program variant */ static struct st_fp_variant * st_translate_fragment_program(struct st_context *st, struct st_fragment_program *stfp, const struct st_fp_variant_key *key) { struct pipe_context *pipe = st->pipe; struct st_fp_variant *variant = CALLOC_STRUCT(st_fp_variant); GLboolean deleteFP = GL_FALSE; GLuint outputMapping[FRAG_RESULT_MAX]; GLuint inputMapping[FRAG_ATTRIB_MAX]; GLuint interpMode[PIPE_MAX_SHADER_INPUTS]; /* XXX size? */ GLuint attr; GLbitfield64 inputsRead; struct ureg_program *ureg; GLboolean write_all = GL_FALSE; ubyte input_semantic_name[PIPE_MAX_SHADER_INPUTS]; ubyte input_semantic_index[PIPE_MAX_SHADER_INPUTS]; GLboolean is_centroid[PIPE_MAX_SHADER_INPUTS]; uint fs_num_inputs = 0; ubyte fs_output_semantic_name[PIPE_MAX_SHADER_OUTPUTS]; ubyte fs_output_semantic_index[PIPE_MAX_SHADER_OUTPUTS]; uint fs_num_outputs = 0; if (!variant) return NULL; assert(!(key->bitmap && key->drawpixels)); if (key->bitmap) { /* glBitmap drawing */ struct gl_fragment_program *fp; /* we free this temp program below */ st_make_bitmap_fragment_program(st, &stfp->Base, &fp, &variant->bitmap_sampler); variant->parameters = _mesa_clone_parameter_list(fp->Base.Parameters); stfp = st_fragment_program(fp); deleteFP = GL_TRUE; } else if (key->drawpixels) { /* glDrawPixels drawing */ struct gl_fragment_program *fp; /* we free this temp program below */ if (key->drawpixels_z || key->drawpixels_stencil) { fp = st_make_drawpix_z_stencil_program(st, key->drawpixels_z, key->drawpixels_stencil); } else { /* RGBA */ st_make_drawpix_fragment_program(st, &stfp->Base, &fp); variant->parameters = _mesa_clone_parameter_list(fp->Base.Parameters); deleteFP = GL_TRUE; } stfp = st_fragment_program(fp); } if (!stfp->glsl_to_tgsi) _mesa_remove_output_reads(&stfp->Base.Base, PROGRAM_OUTPUT); /* * Convert Mesa program inputs to TGSI input register semantics. */ inputsRead = stfp->Base.Base.InputsRead; for (attr = 0; attr < FRAG_ATTRIB_MAX; attr++) { if ((inputsRead & BITFIELD64_BIT(attr)) != 0) { const GLuint slot = fs_num_inputs++; inputMapping[attr] = slot; is_centroid[slot] = (stfp->Base.IsCentroid & BITFIELD64_BIT(attr)) != 0; switch (attr) { case FRAG_ATTRIB_WPOS: input_semantic_name[slot] = TGSI_SEMANTIC_POSITION; input_semantic_index[slot] = 0; interpMode[slot] = TGSI_INTERPOLATE_LINEAR; break; case FRAG_ATTRIB_COL0: input_semantic_name[slot] = TGSI_SEMANTIC_COLOR; input_semantic_index[slot] = 0; interpMode[slot] = st_translate_interp(stfp->Base.InterpQualifier[attr], TRUE); break; case FRAG_ATTRIB_COL1: input_semantic_name[slot] = TGSI_SEMANTIC_COLOR; input_semantic_index[slot] = 1; interpMode[slot] = st_translate_interp(stfp->Base.InterpQualifier[attr], TRUE); break; case FRAG_ATTRIB_FOGC: input_semantic_name[slot] = TGSI_SEMANTIC_FOG; input_semantic_index[slot] = 0; interpMode[slot] = TGSI_INTERPOLATE_PERSPECTIVE; break; case FRAG_ATTRIB_FACE: input_semantic_name[slot] = TGSI_SEMANTIC_FACE; input_semantic_index[slot] = 0; interpMode[slot] = TGSI_INTERPOLATE_CONSTANT; break; case FRAG_ATTRIB_CLIP_DIST0: input_semantic_name[slot] = TGSI_SEMANTIC_CLIPDIST; input_semantic_index[slot] = 0; interpMode[slot] = TGSI_INTERPOLATE_PERSPECTIVE; break; case FRAG_ATTRIB_CLIP_DIST1: input_semantic_name[slot] = TGSI_SEMANTIC_CLIPDIST; input_semantic_index[slot] = 1; interpMode[slot] = TGSI_INTERPOLATE_PERSPECTIVE; break; /* In most cases, there is nothing special about these * inputs, so adopt a convention to use the generic * semantic name and the mesa FRAG_ATTRIB_ number as the * index. * * All that is required is that the vertex shader labels * its own outputs similarly, and that the vertex shader * generates at least every output required by the * fragment shader plus fixed-function hardware (such as * BFC). * * There is no requirement that semantic indexes start at * zero or be restricted to a particular range -- nobody * should be building tables based on semantic index. */ case FRAG_ATTRIB_PNTC: case FRAG_ATTRIB_TEX0: case FRAG_ATTRIB_TEX1: case FRAG_ATTRIB_TEX2: case FRAG_ATTRIB_TEX3: case FRAG_ATTRIB_TEX4: case FRAG_ATTRIB_TEX5: case FRAG_ATTRIB_TEX6: case FRAG_ATTRIB_TEX7: case FRAG_ATTRIB_VAR0: default: /* Actually, let's try and zero-base this just for * readability of the generated TGSI. */ assert(attr >= FRAG_ATTRIB_TEX0); input_semantic_index[slot] = (attr - FRAG_ATTRIB_TEX0); input_semantic_name[slot] = TGSI_SEMANTIC_GENERIC; if (attr == FRAG_ATTRIB_PNTC) interpMode[slot] = TGSI_INTERPOLATE_LINEAR; else interpMode[slot] = st_translate_interp(stfp->Base.InterpQualifier[attr], FALSE); break; } } else { inputMapping[attr] = -1; } } /* * Semantics and mapping for outputs */ { uint numColors = 0; GLbitfield64 outputsWritten = stfp->Base.Base.OutputsWritten; /* if z is written, emit that first */ if (outputsWritten & BITFIELD64_BIT(FRAG_RESULT_DEPTH)) { fs_output_semantic_name[fs_num_outputs] = TGSI_SEMANTIC_POSITION; fs_output_semantic_index[fs_num_outputs] = 0; outputMapping[FRAG_RESULT_DEPTH] = fs_num_outputs; fs_num_outputs++; outputsWritten &= ~(1 << FRAG_RESULT_DEPTH); } if (outputsWritten & BITFIELD64_BIT(FRAG_RESULT_STENCIL)) { fs_output_semantic_name[fs_num_outputs] = TGSI_SEMANTIC_STENCIL; fs_output_semantic_index[fs_num_outputs] = 0; outputMapping[FRAG_RESULT_STENCIL] = fs_num_outputs; fs_num_outputs++; outputsWritten &= ~(1 << FRAG_RESULT_STENCIL); } /* handle remaining outputs (color) */ for (attr = 0; attr < FRAG_RESULT_MAX; attr++) { if (outputsWritten & BITFIELD64_BIT(attr)) { switch (attr) { case FRAG_RESULT_DEPTH: case FRAG_RESULT_STENCIL: /* handled above */ assert(0); break; case FRAG_RESULT_COLOR: write_all = GL_TRUE; /* fallthrough */ default: assert(attr == FRAG_RESULT_COLOR || (FRAG_RESULT_DATA0 <= attr && attr < FRAG_RESULT_MAX)); fs_output_semantic_name[fs_num_outputs] = TGSI_SEMANTIC_COLOR; fs_output_semantic_index[fs_num_outputs] = numColors; outputMapping[attr] = fs_num_outputs; numColors++; break; } fs_num_outputs++; } } } ureg = ureg_create( TGSI_PROCESSOR_FRAGMENT ); if (ureg == NULL) { free(variant); return NULL; } if (ST_DEBUG & DEBUG_MESA) { _mesa_print_program(&stfp->Base.Base); _mesa_print_program_parameters(st->ctx, &stfp->Base.Base); debug_printf("\n"); } if (write_all == GL_TRUE) ureg_property_fs_color0_writes_all_cbufs(ureg, 1); if (stfp->Base.FragDepthLayout != FRAG_DEPTH_LAYOUT_NONE) { switch (stfp->Base.FragDepthLayout) { case FRAG_DEPTH_LAYOUT_ANY: ureg_property_fs_depth_layout(ureg, TGSI_FS_DEPTH_LAYOUT_ANY); break; case FRAG_DEPTH_LAYOUT_GREATER: ureg_property_fs_depth_layout(ureg, TGSI_FS_DEPTH_LAYOUT_GREATER); break; case FRAG_DEPTH_LAYOUT_LESS: ureg_property_fs_depth_layout(ureg, TGSI_FS_DEPTH_LAYOUT_LESS); break; case FRAG_DEPTH_LAYOUT_UNCHANGED: ureg_property_fs_depth_layout(ureg, TGSI_FS_DEPTH_LAYOUT_UNCHANGED); break; default: assert(0); } } if (stfp->glsl_to_tgsi) st_translate_program(st->ctx, TGSI_PROCESSOR_FRAGMENT, ureg, stfp->glsl_to_tgsi, &stfp->Base.Base, /* inputs */ fs_num_inputs, inputMapping, input_semantic_name, input_semantic_index, interpMode, is_centroid, /* outputs */ fs_num_outputs, outputMapping, fs_output_semantic_name, fs_output_semantic_index, FALSE, key->clamp_color ); else st_translate_mesa_program(st->ctx, TGSI_PROCESSOR_FRAGMENT, ureg, &stfp->Base.Base, /* inputs */ fs_num_inputs, inputMapping, input_semantic_name, input_semantic_index, interpMode, /* outputs */ fs_num_outputs, outputMapping, fs_output_semantic_name, fs_output_semantic_index, FALSE, key->clamp_color); variant->tgsi.tokens = ureg_get_tokens( ureg, NULL ); ureg_destroy( ureg ); /* fill in variant */ variant->driver_shader = pipe->create_fs_state(pipe, &variant->tgsi); variant->key = *key; if (ST_DEBUG & DEBUG_TGSI) { tgsi_dump( variant->tgsi.tokens, 0/*TGSI_DUMP_VERBOSE*/ ); debug_printf("\n"); } if (deleteFP) { /* Free the temporary program made above */ struct gl_fragment_program *fp = &stfp->Base; _mesa_reference_fragprog(st->ctx, &fp, NULL); } return variant; }
static void * svga_texture_transfer_map(struct pipe_context *pipe, struct pipe_resource *texture, unsigned level, unsigned usage, const struct pipe_box *box, struct pipe_transfer **ptransfer) { struct svga_context *svga = svga_context(pipe); struct svga_screen *ss = svga_screen(pipe->screen); struct svga_winsys_screen *sws = ss->sws; struct svga_texture *tex = svga_texture(texture); struct svga_transfer *st; unsigned nblocksx, nblocksy; boolean use_direct_map = svga_have_gb_objects(svga) && !svga_have_gb_dma(svga); unsigned d; void *returnVal; int64_t begin = os_time_get(); /* We can't map texture storage directly unless we have GB objects */ if (usage & PIPE_TRANSFER_MAP_DIRECTLY) { if (svga_have_gb_objects(svga)) use_direct_map = TRUE; else return NULL; } st = CALLOC_STRUCT(svga_transfer); if (!st) return NULL; { unsigned w, h; if (use_direct_map) { /* we'll directly access the guest-backed surface */ w = u_minify(texture->width0, level); h = u_minify(texture->height0, level); d = u_minify(texture->depth0, level); } else { /* we'll put the data into a tightly packed buffer */ w = box->width; h = box->height; d = box->depth; } nblocksx = util_format_get_nblocksx(texture->format, w); nblocksy = util_format_get_nblocksy(texture->format, h); } pipe_resource_reference(&st->base.resource, texture); st->base.level = level; st->base.usage = usage; st->base.box = *box; st->base.stride = nblocksx*util_format_get_blocksize(texture->format); st->base.layer_stride = st->base.stride * nblocksy; switch (tex->b.b.target) { case PIPE_TEXTURE_CUBE: case PIPE_TEXTURE_2D_ARRAY: case PIPE_TEXTURE_1D_ARRAY: st->slice = st->base.box.z; st->base.box.z = 0; /* so we don't apply double offsets below */ break; default: st->slice = 0; break; } if (usage & PIPE_TRANSFER_WRITE) { /* record texture upload for HUD */ svga->hud.num_bytes_uploaded += nblocksx * nblocksy * d * util_format_get_blocksize(texture->format); } if (!use_direct_map) { /* Use a DMA buffer */ st->hw_nblocksy = nblocksy; st->hwbuf = svga_winsys_buffer_create(svga, 1, 0, st->hw_nblocksy * st->base.stride * d); while(!st->hwbuf && (st->hw_nblocksy /= 2)) { st->hwbuf = svga_winsys_buffer_create(svga, 1, 0, st->hw_nblocksy * st->base.stride * d); } if (!st->hwbuf) { FREE(st); return NULL; } if (st->hw_nblocksy < nblocksy) { /* We couldn't allocate a hardware buffer big enough for the transfer, * so allocate regular malloc memory instead */ if (0) { debug_printf("%s: failed to allocate %u KB of DMA, " "splitting into %u x %u KB DMA transfers\n", __FUNCTION__, (nblocksy*st->base.stride + 1023)/1024, (nblocksy + st->hw_nblocksy - 1)/st->hw_nblocksy, (st->hw_nblocksy*st->base.stride + 1023)/1024); } st->swbuf = MALLOC(nblocksy * st->base.stride * d); if (!st->swbuf) { sws->buffer_destroy(sws, st->hwbuf); FREE(st); return NULL; } } if (usage & PIPE_TRANSFER_READ) { SVGA3dSurfaceDMAFlags flags; memset(&flags, 0, sizeof flags); svga_transfer_dma(svga, st, SVGA3D_READ_HOST_VRAM, flags); } } else { struct pipe_transfer *transfer = &st->base; struct svga_winsys_surface *surf = tex->handle; if (!surf) { FREE(st); return NULL; } /* If this is the first time mapping to the surface in this * command buffer, clear the dirty masks of this surface. */ if (sws->surface_is_flushed(sws, surf)) { svga_clear_texture_dirty(tex); } if (need_tex_readback(transfer)) { enum pipe_error ret; svga_surfaces_flush(svga); if (svga_have_vgpu10(svga)) { ret = readback_image_vgpu10(svga, surf, st->slice, transfer->level, tex->b.b.last_level + 1); } else { ret = readback_image_vgpu9(svga, surf, st->slice, transfer->level); } svga->hud.num_readbacks++; assert(ret == PIPE_OK); (void) ret; svga_context_flush(svga, NULL); /* * Note: if PIPE_TRANSFER_DISCARD_WHOLE_RESOURCE were specified * we could potentially clear the flag for all faces/layers/mips. */ svga_clear_texture_rendered_to(tex, st->slice, transfer->level); } else { assert(transfer->usage & PIPE_TRANSFER_WRITE); if ((transfer->usage & PIPE_TRANSFER_UNSYNCHRONIZED) == 0) { if (svga_is_texture_dirty(tex, st->slice, transfer->level)) { /* * do a surface flush if the subresource has been modified * in this command buffer. */ svga_surfaces_flush(svga); if (!sws->surface_is_flushed(sws, surf)) { svga->hud.surface_write_flushes++; svga_context_flush(svga, NULL); } } } } if (transfer->usage & PIPE_TRANSFER_WRITE) { /* mark this texture level as dirty */ svga_set_texture_dirty(tex, st->slice, transfer->level); } } st->use_direct_map = use_direct_map; *ptransfer = &st->base; /* * Begin mapping code */ if (st->swbuf) { returnVal = st->swbuf; } else if (!st->use_direct_map) { returnVal = sws->buffer_map(sws, st->hwbuf, usage); } else { SVGA3dSize baseLevelSize; struct svga_texture *tex = svga_texture(texture); struct svga_winsys_surface *surf = tex->handle; uint8_t *map; boolean retry; unsigned offset, mip_width, mip_height; unsigned xoffset = st->base.box.x; unsigned yoffset = st->base.box.y; unsigned zoffset = st->base.box.z; map = svga->swc->surface_map(svga->swc, surf, usage, &retry); if (map == NULL && retry) { /* * At this point, the svga_surfaces_flush() should already have * called in svga_texture_get_transfer(). */ svga_context_flush(svga, NULL); map = svga->swc->surface_map(svga->swc, surf, usage, &retry); } /* * Make sure we return NULL if the map fails */ if (!map) { FREE(st); return map; } /** * Compute the offset to the specific texture slice in the buffer. */ baseLevelSize.width = tex->b.b.width0; baseLevelSize.height = tex->b.b.height0; baseLevelSize.depth = tex->b.b.depth0; offset = svga3dsurface_get_image_offset(tex->key.format, baseLevelSize, tex->b.b.last_level + 1, /* numMips */ st->slice, level); if (level > 0) { assert(offset > 0); } mip_width = u_minify(tex->b.b.width0, level); mip_height = u_minify(tex->b.b.height0, level); offset += svga3dsurface_get_pixel_offset(tex->key.format, mip_width, mip_height, xoffset, yoffset, zoffset); returnVal = (void *) (map + offset); } svga->hud.map_buffer_time += (os_time_get() - begin); svga->hud.num_resources_mapped++; return returnVal; }
static struct pb_buffer * pb_cache_manager_create_buffer(struct pb_manager *_mgr, pb_size size, const struct pb_desc *desc) { struct pb_cache_manager *mgr = pb_cache_manager(_mgr); struct pb_cache_buffer *buf; struct pb_cache_buffer *curr_buf; struct list_head *curr, *next; struct util_time now; pipe_mutex_lock(mgr->mutex); buf = NULL; curr = mgr->delayed.next; next = curr->next; /* search in the expired buffers, freeing them in the process */ util_time_get(&now); while(curr != &mgr->delayed) { curr_buf = LIST_ENTRY(struct pb_cache_buffer, curr, head); if(!buf && pb_cache_is_buffer_compat(curr_buf, size, desc)) buf = curr_buf; else if(util_time_timeout(&curr_buf->start, &curr_buf->end, &now)) _pb_cache_buffer_destroy(curr_buf); else /* This buffer (and all hereafter) are still hot in cache */ break; curr = next; next = curr->next; } /* keep searching in the hot buffers */ if(!buf) { while(curr != &mgr->delayed) { curr_buf = LIST_ENTRY(struct pb_cache_buffer, curr, head); if(pb_cache_is_buffer_compat(curr_buf, size, desc)) { buf = curr_buf; break; } /* no need to check the timeout here */ curr = next; next = curr->next; } } if(buf) { LIST_DEL(&buf->head); pipe_mutex_unlock(mgr->mutex); /* Increase refcount */ pb_reference((struct pb_buffer**)&buf, &buf->base); return &buf->base; } pipe_mutex_unlock(mgr->mutex); buf = CALLOC_STRUCT(pb_cache_buffer); if(!buf) return NULL; buf->buffer = mgr->provider->create_buffer(mgr->provider, size, desc); if(!buf->buffer) { FREE(buf); return NULL; } assert(pipe_is_referenced(&buf->buffer->base.reference)); assert(pb_check_alignment(desc->alignment, buf->buffer->base.alignment)); assert(pb_check_usage(desc->usage, buf->buffer->base.usage)); assert(buf->buffer->base.size >= size); pipe_reference_init(&buf->base.base.reference, 1); buf->base.base.alignment = buf->buffer->base.alignment; buf->base.base.usage = buf->buffer->base.usage; buf->base.base.size = buf->buffer->base.size; buf->base.vtbl = &pb_cache_buffer_vtbl; buf->mgr = mgr; return &buf->base; }