summaryrefslogtreecommitdiffstats
path: root/src/gallium/drivers/lima/lima_state.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/gallium/drivers/lima/lima_state.c')
-rw-r--r--src/gallium/drivers/lima/lima_state.c506
1 files changed, 506 insertions, 0 deletions
diff --git a/src/gallium/drivers/lima/lima_state.c b/src/gallium/drivers/lima/lima_state.c
new file mode 100644
index 00000000000..3691dd9b58d
--- /dev/null
+++ b/src/gallium/drivers/lima/lima_state.c
@@ -0,0 +1,506 @@
+/*
+ * Copyright (c) 2011-2013 Luc Verhaegen <[email protected]>
+ * Copyright (c) 2017-2019 Lima Project
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sub license,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ *
+ */
+
+#include "util/u_memory.h"
+#include "util/u_inlines.h"
+#include "util/u_helpers.h"
+#include "util/u_debug.h"
+
+#include "pipe/p_state.h"
+
+#include "lima_screen.h"
+#include "lima_context.h"
+#include "lima_resource.h"
+
+static void
+lima_set_framebuffer_state(struct pipe_context *pctx,
+ const struct pipe_framebuffer_state *framebuffer)
+{
+ struct lima_context *ctx = lima_context(pctx);
+
+ /* submit need framebuffer info, flush before change it */
+ lima_flush(ctx);
+
+ struct lima_context_framebuffer *fb = &ctx->framebuffer;
+
+ fb->samples = framebuffer->samples;
+
+ pipe_surface_reference(&fb->cbuf, framebuffer->cbufs[0]);
+ pipe_surface_reference(&fb->zsbuf, framebuffer->zsbuf);
+
+ /* need align here? */
+ fb->width = framebuffer->width;
+ fb->height = framebuffer->height;
+
+ int width = align(framebuffer->width, 16) >> 4;
+ int height = align(framebuffer->height, 16) >> 4;
+ if (fb->tiled_w != width || fb->tiled_h != height) {
+ fb->tiled_w = width;
+ fb->tiled_h = height;
+
+ fb->shift_h = 0;
+ fb->shift_w = 0;
+
+ int limit = ctx->plb_max_blk;
+ while ((width * height) > limit) {
+ if (width >= height) {
+ width = (width + 1) >> 1;
+ fb->shift_w++;
+ } else {
+ height = (height + 1) >> 1;
+ fb->shift_h++;
+ }
+ }
+
+ fb->block_w = width;
+ fb->block_h = height;
+
+ fb->shift_min = MIN3(fb->shift_w, fb->shift_h, 2);
+
+ debug_printf("fb dim change tiled=%d/%d block=%d/%d shift=%d/%d/%d\n",
+ fb->tiled_w, fb->tiled_h, fb->block_w, fb->block_h,
+ fb->shift_w, fb->shift_h, fb->shift_min);
+ }
+
+ ctx->dirty |= LIMA_CONTEXT_DIRTY_FRAMEBUFFER;
+}
+
+static void
+lima_set_polygon_stipple(struct pipe_context *pctx,
+ const struct pipe_poly_stipple *stipple)
+{
+
+}
+
+static void *
+lima_create_depth_stencil_alpha_state(struct pipe_context *pctx,
+ const struct pipe_depth_stencil_alpha_state *cso)
+{
+ struct lima_depth_stencil_alpha_state *so;
+
+ so = CALLOC_STRUCT(lima_depth_stencil_alpha_state);
+ if (!so)
+ return NULL;
+
+ so->base = *cso;
+
+ return so;
+}
+
+static void
+lima_bind_depth_stencil_alpha_state(struct pipe_context *pctx, void *hwcso)
+{
+ struct lima_context *ctx = lima_context(pctx);
+
+ ctx->zsa = hwcso;
+ ctx->dirty |= LIMA_CONTEXT_DIRTY_ZSA;
+}
+
+static void
+lima_delete_depth_stencil_alpha_state(struct pipe_context *pctx, void *hwcso)
+{
+ FREE(hwcso);
+}
+
+static void *
+lima_create_rasterizer_state(struct pipe_context *pctx,
+ const struct pipe_rasterizer_state *cso)
+{
+ struct lima_rasterizer_state *so;
+
+ so = CALLOC_STRUCT(lima_rasterizer_state);
+ if (!so)
+ return NULL;
+
+ so->base = *cso;
+
+ return so;
+}
+
+static void
+lima_bind_rasterizer_state(struct pipe_context *pctx, void *hwcso)
+{
+ struct lima_context *ctx = lima_context(pctx);
+
+ ctx->rasterizer = hwcso;
+ ctx->dirty |= LIMA_CONTEXT_DIRTY_RASTERIZER;
+}
+
+static void
+lima_delete_rasterizer_state(struct pipe_context *pctx, void *hwcso)
+{
+ FREE(hwcso);
+}
+
+static void *
+lima_create_blend_state(struct pipe_context *pctx,
+ const struct pipe_blend_state *cso)
+{
+ struct lima_blend_state *so;
+
+ so = CALLOC_STRUCT(lima_blend_state);
+ if (!so)
+ return NULL;
+
+ so->base = *cso;
+
+ return so;
+}
+
+static void
+lima_bind_blend_state(struct pipe_context *pctx, void *hwcso)
+{
+ struct lima_context *ctx = lima_context(pctx);
+
+ ctx->blend = hwcso;
+ ctx->dirty |= LIMA_CONTEXT_DIRTY_BLEND;
+}
+
+static void
+lima_delete_blend_state(struct pipe_context *pctx, void *hwcso)
+{
+ FREE(hwcso);
+}
+
+static void *
+lima_create_vertex_elements_state(struct pipe_context *pctx, unsigned num_elements,
+ const struct pipe_vertex_element *elements)
+{
+ struct lima_vertex_element_state *so;
+
+ so = CALLOC_STRUCT(lima_vertex_element_state);
+ if (!so)
+ return NULL;
+
+ memcpy(so->pipe, elements, sizeof(*elements) * num_elements);
+ so->num_elements = num_elements;
+
+ return so;
+}
+
+static void
+lima_bind_vertex_elements_state(struct pipe_context *pctx, void *hwcso)
+{
+ struct lima_context *ctx = lima_context(pctx);
+
+ ctx->vertex_elements = hwcso;
+ ctx->dirty |= LIMA_CONTEXT_DIRTY_VERTEX_ELEM;
+}
+
+static void
+lima_delete_vertex_elements_state(struct pipe_context *pctx, void *hwcso)
+{
+ FREE(hwcso);
+}
+
+static void
+lima_set_vertex_buffers(struct pipe_context *pctx,
+ unsigned start_slot, unsigned count,
+ const struct pipe_vertex_buffer *vb)
+{
+ struct lima_context *ctx = lima_context(pctx);
+ struct lima_context_vertex_buffer *so = &ctx->vertex_buffers;
+
+ util_set_vertex_buffers_mask(so->vb + start_slot, &so->enabled_mask,
+ vb, start_slot, count);
+ so->count = util_last_bit(so->enabled_mask);
+
+ ctx->dirty |= LIMA_CONTEXT_DIRTY_VERTEX_BUFF;
+}
+
+static void
+lima_set_viewport_states(struct pipe_context *pctx,
+ unsigned start_slot,
+ unsigned num_viewports,
+ const struct pipe_viewport_state *viewport)
+{
+ struct lima_context *ctx = lima_context(pctx);
+
+ /* reverse calculate the parameter of glViewport */
+ ctx->viewport.x = viewport->translate[0] - viewport->scale[0];
+ ctx->viewport.y = fabsf(viewport->translate[1] - fabsf(viewport->scale[1]));
+ ctx->viewport.width = viewport->scale[0] * 2;
+ ctx->viewport.height = fabsf(viewport->scale[1] * 2);
+
+ /* reverse calculate the parameter of glDepthRange */
+ ctx->viewport.near = viewport->translate[2] - viewport->scale[2];
+ ctx->viewport.far = viewport->translate[2] + viewport->scale[2];
+
+ ctx->viewport.transform = *viewport;
+ ctx->dirty |= LIMA_CONTEXT_DIRTY_VIEWPORT;
+}
+
+static void
+lima_set_scissor_states(struct pipe_context *pctx,
+ unsigned start_slot,
+ unsigned num_scissors,
+ const struct pipe_scissor_state *scissor)
+{
+ struct lima_context *ctx = lima_context(pctx);
+
+ ctx->scissor = *scissor;
+ ctx->dirty |= LIMA_CONTEXT_DIRTY_SCISSOR;
+}
+
+static void
+lima_set_blend_color(struct pipe_context *pctx,
+ const struct pipe_blend_color *blend_color)
+{
+ struct lima_context *ctx = lima_context(pctx);
+
+ ctx->blend_color = *blend_color;
+ ctx->dirty |= LIMA_CONTEXT_DIRTY_BLEND_COLOR;
+}
+
+static void
+lima_set_stencil_ref(struct pipe_context *pctx,
+ const struct pipe_stencil_ref *stencil_ref)
+{
+ struct lima_context *ctx = lima_context(pctx);
+
+ ctx->stencil_ref = *stencil_ref;
+ ctx->dirty |= LIMA_CONTEXT_DIRTY_STENCIL_REF;
+}
+
+static void
+lima_set_constant_buffer(struct pipe_context *pctx,
+ enum pipe_shader_type shader, uint index,
+ const struct pipe_constant_buffer *cb)
+{
+ struct lima_context *ctx = lima_context(pctx);
+ struct lima_context_constant_buffer *so = ctx->const_buffer + shader;
+
+ assert(index == 0);
+
+ if (unlikely(!cb)) {
+ so->buffer = NULL;
+ so->size = 0;
+ } else {
+ assert(!cb->buffer);
+
+ so->buffer = cb->user_buffer + cb->buffer_offset;
+ so->size = cb->buffer_size;
+ }
+
+ so->dirty = true;
+ ctx->dirty |= LIMA_CONTEXT_DIRTY_CONST_BUFF;
+
+}
+
+static void *
+lima_create_sampler_state(struct pipe_context *pctx,
+ const struct pipe_sampler_state *cso)
+{
+ struct lima_sampler_state *so = CALLOC_STRUCT(lima_sampler_state);
+ if (!so)
+ return NULL;
+
+ memcpy(so, cso, sizeof(*cso));
+
+ return so;
+}
+
+static void
+lima_sampler_state_delete(struct pipe_context *pctx, void *sstate)
+{
+ free(sstate);
+}
+
+static void
+lima_sampler_states_bind(struct pipe_context *pctx,
+ enum pipe_shader_type shader, unsigned start,
+ unsigned nr, void **hwcso)
+{
+ struct lima_context *ctx = lima_context(pctx);
+ struct lima_texture_stateobj *lima_tex = &ctx->tex_stateobj;
+ unsigned i;
+ unsigned new_nr = 0;
+
+ assert(start == 0);
+
+ for (i = 0; i < nr; i++) {
+ if (hwcso[i])
+ new_nr = i + 1;
+ lima_tex->samplers[i] = hwcso[i];
+ }
+
+ for (; i < lima_tex->num_samplers; i++) {
+ lima_tex->samplers[i] = NULL;
+ }
+
+ lima_tex->num_samplers = new_nr;
+ ctx->dirty |= LIMA_CONTEXT_DIRTY_TEXTURES;
+}
+
+static struct pipe_sampler_view *
+lima_create_sampler_view(struct pipe_context *pctx, struct pipe_resource *prsc,
+ const struct pipe_sampler_view *cso)
+{
+ struct lima_sampler_view *so = CALLOC_STRUCT(lima_sampler_view);
+
+ if (!so)
+ return NULL;
+
+ so->base = *cso;
+
+ pipe_reference(NULL, &prsc->reference);
+ so->base.texture = prsc;
+ so->base.reference.count = 1;
+ so->base.context = pctx;
+
+ return &so->base;
+}
+
+static void
+lima_sampler_view_destroy(struct pipe_context *pctx,
+ struct pipe_sampler_view *pview)
+{
+ struct lima_sampler_view *view = lima_sampler_view(pview);
+
+ pipe_resource_reference(&pview->texture, NULL);
+
+ free(view);
+}
+
+static void
+lima_set_sampler_views(struct pipe_context *pctx,
+ enum pipe_shader_type shader,
+ unsigned start, unsigned nr,
+ struct pipe_sampler_view **views)
+{
+ struct lima_context *ctx = lima_context(pctx);
+ struct lima_texture_stateobj *lima_tex = &ctx->tex_stateobj;
+ int i;
+ unsigned new_nr = 0;
+
+ assert(start == 0);
+
+ for (i = 0; i < nr; i++) {
+ if (views[i])
+ new_nr = i + 1;
+ pipe_sampler_view_reference(&lima_tex->textures[i], views[i]);
+ }
+
+ for (; i < lima_tex->num_textures; i++) {
+ pipe_sampler_view_reference(&lima_tex->textures[i], NULL);
+ }
+
+ lima_tex->num_textures = new_nr;
+ ctx->dirty |= LIMA_CONTEXT_DIRTY_TEXTURES;
+}
+
+static boolean
+lima_set_damage_region(struct pipe_context *pctx, unsigned num_rects, int *rects)
+{
+ struct lima_context *ctx = lima_context(pctx);
+ struct lima_damage_state *damage = &ctx->damage;
+ int i;
+
+ if (damage->region)
+ ralloc_free(damage->region);
+
+ if (!num_rects) {
+ damage->region = NULL;
+ damage->num_region = 0;
+ return true;
+ }
+
+ damage->region = ralloc_size(ctx, sizeof(*damage->region) * num_rects);
+ if (!damage->region) {
+ damage->num_region = 0;
+ return false;
+ }
+
+ for (i = 0; i < num_rects; i++) {
+ struct pipe_scissor_state *r = damage->region + i;
+ /* region in tile unit */
+ r->minx = rects[i * 4] >> 4;
+ r->miny = rects[i * 4 + 1] >> 4;
+ r->maxx = (rects[i * 4] + rects[i * 4 + 2] + 0xf) >> 4;
+ r->maxy = (rects[i * 4 + 1] + rects[i * 4 + 3] + 0xf) >> 4;
+ }
+
+ /* is region aligned to tiles? */
+ damage->aligned = true;
+ for (i = 0; i < num_rects * 4; i++) {
+ if (rects[i] & 0xf) {
+ damage->aligned = false;
+ break;
+ }
+ }
+
+ damage->num_region = num_rects;
+ return true;
+}
+
+void
+lima_state_init(struct lima_context *ctx)
+{
+ ctx->base.set_framebuffer_state = lima_set_framebuffer_state;
+ ctx->base.set_polygon_stipple = lima_set_polygon_stipple;
+ ctx->base.set_viewport_states = lima_set_viewport_states;
+ ctx->base.set_scissor_states = lima_set_scissor_states;
+ ctx->base.set_blend_color = lima_set_blend_color;
+ ctx->base.set_stencil_ref = lima_set_stencil_ref;
+
+ ctx->base.set_vertex_buffers = lima_set_vertex_buffers;
+ ctx->base.set_constant_buffer = lima_set_constant_buffer;
+
+ ctx->base.create_depth_stencil_alpha_state = lima_create_depth_stencil_alpha_state;
+ ctx->base.bind_depth_stencil_alpha_state = lima_bind_depth_stencil_alpha_state;
+ ctx->base.delete_depth_stencil_alpha_state = lima_delete_depth_stencil_alpha_state;
+
+ ctx->base.create_rasterizer_state = lima_create_rasterizer_state;
+ ctx->base.bind_rasterizer_state = lima_bind_rasterizer_state;
+ ctx->base.delete_rasterizer_state = lima_delete_rasterizer_state;
+
+ ctx->base.create_blend_state = lima_create_blend_state;
+ ctx->base.bind_blend_state = lima_bind_blend_state;
+ ctx->base.delete_blend_state = lima_delete_blend_state;
+
+ ctx->base.create_vertex_elements_state = lima_create_vertex_elements_state;
+ ctx->base.bind_vertex_elements_state = lima_bind_vertex_elements_state;
+ ctx->base.delete_vertex_elements_state = lima_delete_vertex_elements_state;
+
+ ctx->base.create_sampler_state = lima_create_sampler_state;
+ ctx->base.delete_sampler_state = lima_sampler_state_delete;
+ ctx->base.bind_sampler_states = lima_sampler_states_bind;
+
+ ctx->base.create_sampler_view = lima_create_sampler_view;
+ ctx->base.sampler_view_destroy = lima_sampler_view_destroy;
+ ctx->base.set_sampler_views = lima_set_sampler_views;
+}
+
+void
+lima_state_fini(struct lima_context *ctx)
+{
+ struct lima_context_vertex_buffer *so = &ctx->vertex_buffers;
+
+ util_set_vertex_buffers_mask(so->vb, &so->enabled_mask, NULL,
+ 0, ARRAY_SIZE(so->vb));
+
+ pipe_surface_reference(&ctx->framebuffer.cbuf, NULL);
+ pipe_surface_reference(&ctx->framebuffer.zsbuf, NULL);
+}