blob: cd910fbf3dea093ea1c13630ef865e968eac2ffe [file] [log] [blame]
/*
* Copyright (c) 2011-2013 Luc Verhaegen <libv@skynet.be>
* 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->base.samples = framebuffer->samples;
fb->base.nr_cbufs = framebuffer->nr_cbufs;
pipe_surface_reference(&fb->base.cbufs[0], framebuffer->cbufs[0]);
pipe_surface_reference(&fb->base.zsbuf, framebuffer->zsbuf);
/* need align here? */
fb->base.width = framebuffer->width;
fb->base.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) {
struct lima_screen *screen = lima_screen(ctx->base.screen);
fb->tiled_w = width;
fb->tiled_h = height;
fb->shift_h = 0;
fb->shift_w = 0;
int limit = screen->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.left = viewport->translate[0] - fabsf(viewport->scale[0]);
ctx->viewport.right = viewport->translate[0] + fabsf(viewport->scale[0]);
ctx->viewport.bottom = viewport->translate[1] - fabsf(viewport->scale[1]);
ctx->viewport.top = viewport->translate[1] + fabsf(viewport->scale[1]);
/* reverse calculate the parameter of glDepthRange */
float near, far;
near = viewport->translate[2] - viewport->scale[2];
far = viewport->translate[2] + viewport->scale[2];
ctx->viewport.near = MIN2(near, far);
ctx->viewport.far = MAX2(near, far);
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 void
lima_set_sample_mask(struct pipe_context *pctx,
unsigned sample_mask)
{
}
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;
ctx->base.set_sample_mask = lima_set_sample_mask;
}
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.base.cbufs[0], NULL);
pipe_surface_reference(&ctx->framebuffer.base.zsbuf, NULL);
}