Path: blob/21.2-virgl/src/gallium/drivers/etnaviv/etnaviv_context.c
4570 views
/*1* Copyright (c) 2012-2015 Etnaviv Project2*3* Permission is hereby granted, free of charge, to any person obtaining a4* copy of this software and associated documentation files (the "Software"),5* to deal in the Software without restriction, including without limitation6* the rights to use, copy, modify, merge, publish, distribute, sub license,7* and/or sell copies of the Software, and to permit persons to whom the8* Software is furnished to do so, subject to the following conditions:9*10* The above copyright notice and this permission notice (including the11* next paragraph) shall be included in all copies or substantial portions12* of the Software.13*14* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR15* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,16* FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL17* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER18* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING19* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER20* DEALINGS IN THE SOFTWARE.21*22* Authors:23* Wladimir J. van der Laan <[email protected]>24* Christian Gmeiner <[email protected]>25*/2627#include "etnaviv_context.h"2829#include "etnaviv_blend.h"30#include "etnaviv_clear_blit.h"31#include "etnaviv_compiler.h"32#include "etnaviv_debug.h"33#include "etnaviv_emit.h"34#include "etnaviv_fence.h"35#include "etnaviv_query.h"36#include "etnaviv_query_acc.h"37#include "etnaviv_rasterizer.h"38#include "etnaviv_resource.h"39#include "etnaviv_screen.h"40#include "etnaviv_shader.h"41#include "etnaviv_state.h"42#include "etnaviv_surface.h"43#include "etnaviv_texture.h"44#include "etnaviv_transfer.h"45#include "etnaviv_translate.h"46#include "etnaviv_zsa.h"4748#include "pipe/p_context.h"49#include "pipe/p_state.h"50#include "util/hash_table.h"51#include "util/u_blitter.h"52#include "util/u_draw.h"53#include "util/u_helpers.h"54#include "util/u_memory.h"55#include "util/u_prim.h"56#include "util/u_upload_mgr.h"5758#include "hw/common.xml.h"5960static inline void61etna_emit_nop_with_data(struct etna_cmd_stream *stream, uint32_t value)62{63etna_cmd_stream_emit(stream, VIV_FE_NOP_HEADER_OP_NOP);64etna_cmd_stream_emit(stream, value);65}6667static void68etna_emit_string_marker(struct pipe_context *pctx, const char *string, int len)69{70struct etna_context *ctx = etna_context(pctx);71struct etna_cmd_stream *stream = ctx->stream;72const uint32_t *buf = (const void *)string;7374etna_cmd_stream_reserve(stream, len * 2);7576while (len >= 4) {77etna_emit_nop_with_data(stream, *buf);78buf++;79len -= 4;80}8182/* copy remainder bytes without reading past end of input string */83if (len > 0) {84uint32_t w = 0;85memcpy(&w, buf, len);86etna_emit_nop_with_data(stream, w);87}88}8990static void91etna_context_destroy(struct pipe_context *pctx)92{93struct etna_context *ctx = etna_context(pctx);9495mtx_lock(&ctx->lock);9697if (ctx->used_resources_read) {9899/*100* There should be no resources tracked in the context when it's being101* destroyed. Be sure there are none to avoid memory leaks on buggy102* programs.103*/104set_foreach(ctx->used_resources_read, entry) {105struct etna_resource *rsc = (struct etna_resource *)entry->key;106107mtx_lock(&rsc->lock);108_mesa_set_remove_key(rsc->pending_ctx, ctx);109mtx_unlock(&rsc->lock);110}111_mesa_set_destroy(ctx->used_resources_read, NULL);112113}114if (ctx->used_resources_write) {115116/*117* There should be no resources tracked in the context when it's being118* destroyed. Be sure there are none to avoid memory leaks on buggy119* programs.120*/121set_foreach(ctx->used_resources_write, entry) {122struct etna_resource *rsc = (struct etna_resource *)entry->key;123124mtx_lock(&rsc->lock);125_mesa_set_remove_key(rsc->pending_ctx, ctx);126mtx_unlock(&rsc->lock);127}128_mesa_set_destroy(ctx->used_resources_write, NULL);129130}131if (ctx->flush_resources)132_mesa_set_destroy(ctx->flush_resources, NULL);133134mtx_unlock(&ctx->lock);135136if (ctx->dummy_desc_bo)137etna_bo_del(ctx->dummy_desc_bo);138139if (ctx->dummy_rt)140etna_bo_del(ctx->dummy_rt);141142util_copy_framebuffer_state(&ctx->framebuffer_s, NULL);143144if (ctx->primconvert)145util_primconvert_destroy(ctx->primconvert);146147if (ctx->blitter)148util_blitter_destroy(ctx->blitter);149150if (pctx->stream_uploader)151u_upload_destroy(pctx->stream_uploader);152153if (ctx->stream)154etna_cmd_stream_del(ctx->stream);155156slab_destroy_child(&ctx->transfer_pool);157158if (ctx->in_fence_fd != -1)159close(ctx->in_fence_fd);160161mtx_destroy(&ctx->lock);162163FREE(pctx);164}165166/* Update render state where needed based on draw operation */167static void168etna_update_state_for_draw(struct etna_context *ctx, const struct pipe_draw_info *info)169{170/* Handle primitive restart:171* - If not an indexed draw, we don't care about the state of the primitive restart bit.172* - Otherwise, set the bit in INDEX_STREAM_CONTROL in the index buffer state173* accordingly174* - If the value of the INDEX_STREAM_CONTROL register changed due to this, or175* primitive restart is enabled and the restart index changed, mark the index176* buffer state as dirty177*/178179if (info->index_size) {180uint32_t new_control = ctx->index_buffer.FE_INDEX_STREAM_CONTROL;181182if (info->primitive_restart)183new_control |= VIVS_FE_INDEX_STREAM_CONTROL_PRIMITIVE_RESTART;184else185new_control &= ~VIVS_FE_INDEX_STREAM_CONTROL_PRIMITIVE_RESTART;186187if (ctx->index_buffer.FE_INDEX_STREAM_CONTROL != new_control ||188(info->primitive_restart && ctx->index_buffer.FE_PRIMITIVE_RESTART_INDEX != info->restart_index)) {189ctx->index_buffer.FE_INDEX_STREAM_CONTROL = new_control;190ctx->index_buffer.FE_PRIMITIVE_RESTART_INDEX = info->restart_index;191ctx->dirty |= ETNA_DIRTY_INDEX_BUFFER;192}193}194}195196static bool197etna_get_vs(struct etna_context *ctx, struct etna_shader_key key)198{199const struct etna_shader_variant *old = ctx->shader.vs;200201ctx->shader.vs = etna_shader_variant(ctx->shader.bind_vs, key, &ctx->debug);202203if (!ctx->shader.vs)204return false;205206if (old != ctx->shader.vs)207ctx->dirty |= ETNA_DIRTY_SHADER;208209return true;210}211212static bool213etna_get_fs(struct etna_context *ctx, struct etna_shader_key key)214{215const struct etna_shader_variant *old = ctx->shader.fs;216217ctx->shader.fs = etna_shader_variant(ctx->shader.bind_fs, key, &ctx->debug);218219if (!ctx->shader.fs)220return false;221222if (old != ctx->shader.fs)223ctx->dirty |= ETNA_DIRTY_SHADER;224225return true;226}227228static void229etna_draw_vbo(struct pipe_context *pctx, const struct pipe_draw_info *info,230unsigned drawid_offset,231const struct pipe_draw_indirect_info *indirect,232const struct pipe_draw_start_count_bias *draws,233unsigned num_draws)234{235if (num_draws > 1) {236util_draw_multi(pctx, info, drawid_offset, indirect, draws, num_draws);237return;238}239240if (!indirect && (!draws[0].count || !info->instance_count))241return;242243struct etna_context *ctx = etna_context(pctx);244struct etna_screen *screen = ctx->screen;245struct pipe_framebuffer_state *pfb = &ctx->framebuffer_s;246uint32_t draw_mode;247unsigned i;248249if (!indirect &&250!info->primitive_restart &&251!u_trim_pipe_prim(info->mode, (unsigned*)&draws[0].count))252return;253254if (ctx->vertex_elements == NULL || ctx->vertex_elements->num_elements == 0)255return; /* Nothing to do */256257if (!(ctx->prim_hwsupport & (1 << info->mode))) {258struct primconvert_context *primconvert = ctx->primconvert;259util_primconvert_save_rasterizer_state(primconvert, ctx->rasterizer);260util_primconvert_draw_vbo(primconvert, info, drawid_offset, indirect, draws, num_draws);261return;262}263264int prims = u_decomposed_prims_for_vertices(info->mode, draws[0].count);265if (unlikely(prims <= 0)) {266DBG("Invalid draw primitive mode=%i or no primitives to be drawn", info->mode);267return;268}269270draw_mode = translate_draw_mode(info->mode);271if (draw_mode == ETNA_NO_MATCH) {272BUG("Unsupported draw mode");273return;274}275276/* Upload a user index buffer. */277unsigned index_offset = 0;278struct pipe_resource *indexbuf = NULL;279280if (info->index_size) {281indexbuf = info->has_user_indices ? NULL : info->index.resource;282if (info->has_user_indices &&283!util_upload_index_buffer(pctx, info, &draws[0], &indexbuf, &index_offset, 4)) {284BUG("Index buffer upload failed.");285return;286}287/* Add start to index offset, when rendering indexed */288index_offset += draws[0].start * info->index_size;289290ctx->index_buffer.FE_INDEX_STREAM_BASE_ADDR.bo = etna_resource(indexbuf)->bo;291ctx->index_buffer.FE_INDEX_STREAM_BASE_ADDR.offset = index_offset;292ctx->index_buffer.FE_INDEX_STREAM_BASE_ADDR.flags = ETNA_RELOC_READ;293ctx->index_buffer.FE_INDEX_STREAM_CONTROL = translate_index_size(info->index_size);294295if (!ctx->index_buffer.FE_INDEX_STREAM_BASE_ADDR.bo) {296BUG("Unsupported or no index buffer");297return;298}299} else {300ctx->index_buffer.FE_INDEX_STREAM_BASE_ADDR.bo = 0;301ctx->index_buffer.FE_INDEX_STREAM_BASE_ADDR.offset = 0;302ctx->index_buffer.FE_INDEX_STREAM_BASE_ADDR.flags = 0;303ctx->index_buffer.FE_INDEX_STREAM_CONTROL = 0;304}305ctx->dirty |= ETNA_DIRTY_INDEX_BUFFER;306307struct etna_shader_key key = {308.front_ccw = ctx->rasterizer->front_ccw,309.sprite_coord_enable = ctx->rasterizer->sprite_coord_enable,310.sprite_coord_yinvert = !!ctx->rasterizer->sprite_coord_mode,311};312313if (pfb->cbufs[0])314key.frag_rb_swap = !!translate_pe_format_rb_swap(pfb->cbufs[0]->format);315316if (!etna_get_vs(ctx, key) || !etna_get_fs(ctx, key)) {317BUG("compiled shaders are not okay");318return;319}320321/* Update any derived state */322if (!etna_state_update(ctx))323return;324325mtx_lock(&ctx->lock);326327/*328* Figure out the buffers/features we need:329*/330if (etna_depth_enabled(ctx))331resource_written(ctx, pfb->zsbuf->texture);332333if (etna_stencil_enabled(ctx))334resource_written(ctx, pfb->zsbuf->texture);335336for (i = 0; i < pfb->nr_cbufs; i++) {337struct pipe_resource *surf;338339if (!pfb->cbufs[i])340continue;341342surf = pfb->cbufs[i]->texture;343resource_written(ctx, surf);344}345346/* Mark constant buffers as being read */347u_foreach_bit(i, ctx->constant_buffer[PIPE_SHADER_VERTEX].enabled_mask)348resource_read(ctx, ctx->constant_buffer[PIPE_SHADER_VERTEX].cb[i].buffer);349350u_foreach_bit(i, ctx->constant_buffer[PIPE_SHADER_FRAGMENT].enabled_mask)351resource_read(ctx, ctx->constant_buffer[PIPE_SHADER_FRAGMENT].cb[i].buffer);352353/* Mark VBOs as being read */354u_foreach_bit(i, ctx->vertex_buffer.enabled_mask) {355assert(!ctx->vertex_buffer.vb[i].is_user_buffer);356resource_read(ctx, ctx->vertex_buffer.vb[i].buffer.resource);357}358359/* Mark index buffer as being read */360resource_read(ctx, indexbuf);361362/* Mark textures as being read */363for (i = 0; i < PIPE_MAX_SAMPLERS; i++) {364if (ctx->sampler_view[i]) {365resource_read(ctx, ctx->sampler_view[i]->texture);366367/* if texture was modified since the last update,368* we need to clear the texture cache and possibly369* resolve/update ts370*/371etna_update_sampler_source(ctx->sampler_view[i], i);372}373}374375ctx->stats.prims_generated += u_reduced_prims_for_vertices(info->mode, draws[0].count);376ctx->stats.draw_calls++;377378/* Update state for this draw operation */379etna_update_state_for_draw(ctx, info);380381/* First, sync state, then emit DRAW_PRIMITIVES or DRAW_INDEXED_PRIMITIVES */382etna_emit_state(ctx);383384if (screen->specs.halti >= 2) {385/* On HALTI2+ (GC3000 and higher) only use instanced drawing commands, as the blob does */386etna_draw_instanced(ctx->stream, info->index_size, draw_mode, info->instance_count,387draws[0].count, info->index_size ? draws->index_bias : draws[0].start);388} else {389if (info->index_size)390etna_draw_indexed_primitives(ctx->stream, draw_mode, 0, prims, draws->index_bias);391else392etna_draw_primitives(ctx->stream, draw_mode, draws[0].start, prims);393}394395if (DBG_ENABLED(ETNA_DBG_DRAW_STALL)) {396/* Stall the FE after every draw operation. This allows better397* debug of GPU hang conditions, as the FE will indicate which398* draw op has caused the hang. */399etna_stall(ctx->stream, SYNC_RECIPIENT_FE, SYNC_RECIPIENT_PE);400}401mtx_unlock(&ctx->lock);402403if (DBG_ENABLED(ETNA_DBG_FLUSH_ALL))404pctx->flush(pctx, NULL, 0);405406if (ctx->framebuffer_s.cbufs[0])407etna_resource(ctx->framebuffer_s.cbufs[0]->texture)->seqno++;408if (ctx->framebuffer_s.zsbuf)409etna_resource(ctx->framebuffer_s.zsbuf->texture)->seqno++;410if (info->index_size && indexbuf != info->index.resource)411pipe_resource_reference(&indexbuf, NULL);412}413414static void415etna_reset_gpu_state(struct etna_context *ctx)416{417struct etna_cmd_stream *stream = ctx->stream;418struct etna_screen *screen = ctx->screen;419420etna_set_state(stream, VIVS_GL_API_MODE, VIVS_GL_API_MODE_OPENGL);421etna_set_state(stream, VIVS_GL_VERTEX_ELEMENT_CONFIG, 0x00000001);422etna_set_state(stream, VIVS_PA_W_CLIP_LIMIT, 0x34000001);423etna_set_state(stream, VIVS_PA_FLAGS, 0x00000000); /* blob sets ZCONVERT_BYPASS on GC3000+, this messes up z for us */424etna_set_state(stream, VIVS_PA_VIEWPORT_UNK00A80, 0x38a01404);425etna_set_state(stream, VIVS_PA_VIEWPORT_UNK00A84, fui(8192.0));426etna_set_state(stream, VIVS_PA_ZFARCLIPPING, 0x00000000);427etna_set_state(stream, VIVS_RA_HDEPTH_CONTROL, 0x00007000);428etna_set_state(stream, VIVS_PS_CONTROL_EXT, 0x00000000);429430/* There is no HALTI0 specific state */431if (screen->specs.halti >= 1) { /* Only on HALTI1+ */432etna_set_state(stream, VIVS_VS_HALTI1_UNK00884, 0x00000808);433}434if (screen->specs.halti >= 2) { /* Only on HALTI2+ */435etna_set_state(stream, VIVS_RA_UNK00E0C, 0x00000000);436}437if (screen->specs.halti >= 3) { /* Only on HALTI3+ */438etna_set_state(stream, VIVS_PS_HALTI3_UNK0103C, 0x76543210);439}440if (screen->specs.halti >= 4) { /* Only on HALTI4+ */441etna_set_state(stream, VIVS_PS_MSAA_CONFIG, 0x6fffffff & 0xf70fffff & 0xfff6ffff &4420xffff6fff & 0xfffff6ff & 0xffffff7f);443etna_set_state(stream, VIVS_PE_HALTI4_UNK014C0, 0x00000000);444}445if (screen->specs.halti >= 5) { /* Only on HALTI5+ */446etna_set_state(stream, VIVS_NTE_DESCRIPTOR_UNK14C40, 0x00000001);447etna_set_state(stream, VIVS_FE_HALTI5_UNK007D8, 0x00000002);448etna_set_state(stream, VIVS_PS_SAMPLER_BASE, 0x00000000);449etna_set_state(stream, VIVS_VS_SAMPLER_BASE, 0x00000020);450etna_set_state(stream, VIVS_SH_CONFIG, VIVS_SH_CONFIG_RTNE_ROUNDING);451} else { /* Only on pre-HALTI5 */452etna_set_state(stream, VIVS_GL_UNK03838, 0x00000000);453etna_set_state(stream, VIVS_GL_UNK03854, 0x00000000);454}455456if (!screen->specs.use_blt) {457/* Enable SINGLE_BUFFER for resolve, if supported */458etna_set_state(stream, VIVS_RS_SINGLE_BUFFER, COND(screen->specs.single_buffer, VIVS_RS_SINGLE_BUFFER_ENABLE));459}460461if (screen->specs.halti >= 5) {462/* TXDESC cache flush - do this once at the beginning, as texture463* descriptors are only written by the CPU once, then patched by the kernel464* before command stream submission. It does not need flushing if the465* referenced image data changes.466*/467etna_set_state(stream, VIVS_NTE_DESCRIPTOR_FLUSH, 0);468etna_set_state(stream, VIVS_GL_FLUSH_CACHE,469VIVS_GL_FLUSH_CACHE_DESCRIPTOR_UNK12 |470VIVS_GL_FLUSH_CACHE_DESCRIPTOR_UNK13);471472/* Icache invalidate (should do this on shader change?) */473etna_set_state(stream, VIVS_VS_ICACHE_INVALIDATE,474VIVS_VS_ICACHE_INVALIDATE_UNK0 | VIVS_VS_ICACHE_INVALIDATE_UNK1 |475VIVS_VS_ICACHE_INVALIDATE_UNK2 | VIVS_VS_ICACHE_INVALIDATE_UNK3 |476VIVS_VS_ICACHE_INVALIDATE_UNK4);477}478479ctx->dirty = ~0L;480ctx->dirty_sampler_views = ~0L;481}482483static void484etna_flush(struct pipe_context *pctx, struct pipe_fence_handle **fence,485enum pipe_flush_flags flags)486{487struct etna_context *ctx = etna_context(pctx);488int out_fence_fd = -1;489490mtx_lock(&ctx->lock);491492list_for_each_entry(struct etna_acc_query, aq, &ctx->active_acc_queries, node)493etna_acc_query_suspend(aq, ctx);494495/* flush all resources that need an implicit flush */496set_foreach(ctx->flush_resources, entry) {497struct pipe_resource *prsc = (struct pipe_resource *)entry->key;498499pctx->flush_resource(pctx, prsc);500}501_mesa_set_clear(ctx->flush_resources, NULL);502503etna_cmd_stream_flush(ctx->stream, ctx->in_fence_fd,504(flags & PIPE_FLUSH_FENCE_FD) ? &out_fence_fd : NULL);505506list_for_each_entry(struct etna_acc_query, aq, &ctx->active_acc_queries, node)507etna_acc_query_resume(aq, ctx);508509if (fence)510*fence = etna_fence_create(pctx, out_fence_fd);511512/*513* Go through all _resources_ pending in this _context_ and mark them as514* not pending in this _context_ anymore, since they were just flushed.515*/516set_foreach(ctx->used_resources_read, entry) {517struct etna_resource *rsc = (struct etna_resource *)entry->key;518struct pipe_resource *referenced = &rsc->base;519520mtx_lock(&rsc->lock);521522_mesa_set_remove_key(rsc->pending_ctx, ctx);523524/* if resource has no pending ctx's reset its status */525if (_mesa_set_next_entry(rsc->pending_ctx, NULL) == NULL)526rsc->status &= ~ETNA_PENDING_READ;527528mtx_unlock(&rsc->lock);529530pipe_resource_reference(&referenced, NULL);531}532_mesa_set_clear(ctx->used_resources_read, NULL);533534set_foreach(ctx->used_resources_write, entry) {535struct etna_resource *rsc = (struct etna_resource *)entry->key;536struct pipe_resource *referenced = &rsc->base;537538mtx_lock(&rsc->lock);539_mesa_set_remove_key(rsc->pending_ctx, ctx);540541/* if resource has no pending ctx's reset its status */542if (_mesa_set_next_entry(rsc->pending_ctx, NULL) == NULL)543rsc->status &= ~ETNA_PENDING_WRITE;544mtx_unlock(&rsc->lock);545546pipe_resource_reference(&referenced, NULL);547}548_mesa_set_clear(ctx->used_resources_write, NULL);549550etna_reset_gpu_state(ctx);551mtx_unlock(&ctx->lock);552}553554static void555etna_context_force_flush(struct etna_cmd_stream *stream, void *priv)556{557struct pipe_context *pctx = priv;558559pctx->flush(pctx, NULL, 0);560561}562563static void564etna_set_debug_callback(struct pipe_context *pctx,565const struct pipe_debug_callback *cb)566{567struct etna_context *ctx = etna_context(pctx);568569if (cb)570ctx->debug = *cb;571else572memset(&ctx->debug, 0, sizeof(ctx->debug));573}574575struct pipe_context *576etna_context_create(struct pipe_screen *pscreen, void *priv, unsigned flags)577{578struct etna_context *ctx = CALLOC_STRUCT(etna_context);579struct etna_screen *screen;580struct pipe_context *pctx;581582if (ctx == NULL)583return NULL;584585pctx = &ctx->base;586pctx->priv = ctx;587pctx->screen = pscreen;588pctx->stream_uploader = u_upload_create_default(pctx);589if (!pctx->stream_uploader)590goto fail;591pctx->const_uploader = pctx->stream_uploader;592593screen = etna_screen(pscreen);594ctx->stream = etna_cmd_stream_new(screen->pipe, 0x2000,595&etna_context_force_flush, pctx);596if (ctx->stream == NULL)597goto fail;598599ctx->used_resources_read = _mesa_set_create(NULL, _mesa_hash_pointer,600_mesa_key_pointer_equal);601if (!ctx->used_resources_read)602goto fail;603604ctx->used_resources_write = _mesa_set_create(NULL, _mesa_hash_pointer,605_mesa_key_pointer_equal);606if (!ctx->used_resources_write)607goto fail;608609ctx->flush_resources = _mesa_set_create(NULL, _mesa_hash_pointer,610_mesa_key_pointer_equal);611if (!ctx->flush_resources)612goto fail;613614mtx_init(&ctx->lock, mtx_recursive);615616/* context ctxate setup */617ctx->screen = screen;618/* need some sane default in case gallium frontends don't set some state: */619ctx->sample_mask = 0xffff;620621/* Set sensible defaults for state */622etna_reset_gpu_state(ctx);623624ctx->in_fence_fd = -1;625626pctx->destroy = etna_context_destroy;627pctx->draw_vbo = etna_draw_vbo;628pctx->flush = etna_flush;629pctx->set_debug_callback = etna_set_debug_callback;630pctx->create_fence_fd = etna_create_fence_fd;631pctx->fence_server_sync = etna_fence_server_sync;632pctx->emit_string_marker = etna_emit_string_marker;633634/* creation of compile states */635pctx->create_blend_state = etna_blend_state_create;636pctx->create_rasterizer_state = etna_rasterizer_state_create;637pctx->create_depth_stencil_alpha_state = etna_zsa_state_create;638639etna_clear_blit_init(pctx);640etna_query_context_init(pctx);641etna_state_init(pctx);642etna_surface_init(pctx);643etna_shader_init(pctx);644etna_texture_init(pctx);645etna_transfer_init(pctx);646647ctx->blitter = util_blitter_create(pctx);648if (!ctx->blitter)649goto fail;650651/* Generate the bitmask of supported draw primitives. */652ctx->prim_hwsupport = 1 << PIPE_PRIM_POINTS |6531 << PIPE_PRIM_LINES |6541 << PIPE_PRIM_LINE_STRIP |6551 << PIPE_PRIM_TRIANGLES |6561 << PIPE_PRIM_TRIANGLE_FAN;657658/* TODO: The bug relates only to indexed draws, but here we signal659* that there is no support for triangle strips at all. This should660* be refined.661*/662if (VIV_FEATURE(ctx->screen, chipMinorFeatures2, BUG_FIXES8))663ctx->prim_hwsupport |= 1 << PIPE_PRIM_TRIANGLE_STRIP;664665if (VIV_FEATURE(ctx->screen, chipMinorFeatures2, LINE_LOOP))666ctx->prim_hwsupport |= 1 << PIPE_PRIM_LINE_LOOP;667668ctx->primconvert = util_primconvert_create(pctx, ctx->prim_hwsupport);669if (!ctx->primconvert)670goto fail;671672slab_create_child(&ctx->transfer_pool, &screen->transfer_pool);673list_inithead(&ctx->active_acc_queries);674675/* create dummy RT buffer, used when rendering with no color buffer */676ctx->dummy_rt = etna_bo_new(ctx->screen->dev, 64 * 64 * 4,677DRM_ETNA_GEM_CACHE_WC);678if (!ctx->dummy_rt)679goto fail;680681ctx->dummy_rt_reloc.bo = ctx->dummy_rt;682ctx->dummy_rt_reloc.offset = 0;683ctx->dummy_rt_reloc.flags = ETNA_RELOC_READ | ETNA_RELOC_WRITE;684685if (screen->specs.halti >= 5) {686/* Create an empty dummy texture descriptor */687ctx->dummy_desc_bo = etna_bo_new(ctx->screen->dev, 0x100, DRM_ETNA_GEM_CACHE_WC);688if (!ctx->dummy_desc_bo)689goto fail;690uint32_t *buf = etna_bo_map(ctx->dummy_desc_bo);691etna_bo_cpu_prep(ctx->dummy_desc_bo, DRM_ETNA_PREP_WRITE);692memset(buf, 0, 0x100);693etna_bo_cpu_fini(ctx->dummy_desc_bo);694ctx->DUMMY_DESC_ADDR.bo = ctx->dummy_desc_bo;695ctx->DUMMY_DESC_ADDR.offset = 0;696ctx->DUMMY_DESC_ADDR.flags = ETNA_RELOC_READ;697}698699return pctx;700701fail:702pctx->destroy(pctx);703704return NULL;705}706707708