1/* 2 * Copyright (c) 2011-2013 Luc Verhaegen <libv@skynet.be> 3 * Copyright (c) 2017-2019 Lima Project 4 * 5 * Permission is hereby granted, free of charge, to any person obtaining a 6 * copy of this software and associated documentation files (the "Software"), 7 * to deal in the Software without restriction, including without limitation 8 * the rights to use, copy, modify, merge, publish, distribute, sub license, 9 * and/or sell copies of the Software, and to permit persons to whom the 10 * Software is furnished to do so, subject to the following conditions: 11 * 12 * The above copyright notice and this permission notice (including the 13 * next paragraph) shall be included in all copies or substantial portions 14 * of the Software. 15 * 16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL 19 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 21 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 22 * DEALINGS IN THE SOFTWARE. 23 * 24 */ 25 26#include "util/u_memory.h" 27#include "util/u_inlines.h" 28#include "util/u_helpers.h" 29#include "util/u_debug.h" 30 31#include "pipe/p_state.h" 32 33#include "lima_screen.h" 34#include "lima_context.h" 35#include "lima_resource.h" 36 37static void 38lima_set_framebuffer_state(struct pipe_context *pctx, 39 const struct pipe_framebuffer_state *framebuffer) 40{ 41 struct lima_context *ctx = lima_context(pctx); 42 43 /* submit need framebuffer info, flush before change it */ 44 lima_flush(ctx); 45 46 struct lima_context_framebuffer *fb = &ctx->framebuffer; 47 48 fb->base.samples = framebuffer->samples; 49 50 fb->base.nr_cbufs = framebuffer->nr_cbufs; 51 pipe_surface_reference(&fb->base.cbufs[0], framebuffer->cbufs[0]); 52 pipe_surface_reference(&fb->base.zsbuf, framebuffer->zsbuf); 53 54 /* need align here? */ 55 fb->base.width = framebuffer->width; 56 fb->base.height = framebuffer->height; 57 58 int width = align(framebuffer->width, 16) >> 4; 59 int height = align(framebuffer->height, 16) >> 4; 60 if (fb->tiled_w != width || fb->tiled_h != height) { 61 fb->tiled_w = width; 62 fb->tiled_h = height; 63 64 fb->shift_h = 0; 65 fb->shift_w = 0; 66 67 int limit = ctx->plb_max_blk; 68 while ((width * height) > limit) { 69 if (width >= height) { 70 width = (width + 1) >> 1; 71 fb->shift_w++; 72 } else { 73 height = (height + 1) >> 1; 74 fb->shift_h++; 75 } 76 } 77 78 fb->block_w = width; 79 fb->block_h = height; 80 81 fb->shift_min = MIN3(fb->shift_w, fb->shift_h, 2); 82 83 debug_printf("fb dim change tiled=%d/%d block=%d/%d shift=%d/%d/%d\n", 84 fb->tiled_w, fb->tiled_h, fb->block_w, fb->block_h, 85 fb->shift_w, fb->shift_h, fb->shift_min); 86 } 87 88 ctx->dirty |= LIMA_CONTEXT_DIRTY_FRAMEBUFFER; 89} 90 91static void 92lima_set_polygon_stipple(struct pipe_context *pctx, 93 const struct pipe_poly_stipple *stipple) 94{ 95 96} 97 98static void * 99lima_create_depth_stencil_alpha_state(struct pipe_context *pctx, 100 const struct pipe_depth_stencil_alpha_state *cso) 101{ 102 struct lima_depth_stencil_alpha_state *so; 103 104 so = CALLOC_STRUCT(lima_depth_stencil_alpha_state); 105 if (!so) 106 return NULL; 107 108 so->base = *cso; 109 110 return so; 111} 112 113static void 114lima_bind_depth_stencil_alpha_state(struct pipe_context *pctx, void *hwcso) 115{ 116 struct lima_context *ctx = lima_context(pctx); 117 118 ctx->zsa = hwcso; 119 ctx->dirty |= LIMA_CONTEXT_DIRTY_ZSA; 120} 121 122static void 123lima_delete_depth_stencil_alpha_state(struct pipe_context *pctx, void *hwcso) 124{ 125 FREE(hwcso); 126} 127 128static void * 129lima_create_rasterizer_state(struct pipe_context *pctx, 130 const struct pipe_rasterizer_state *cso) 131{ 132 struct lima_rasterizer_state *so; 133 134 so = CALLOC_STRUCT(lima_rasterizer_state); 135 if (!so) 136 return NULL; 137 138 so->base = *cso; 139 140 return so; 141} 142 143static void 144lima_bind_rasterizer_state(struct pipe_context *pctx, void *hwcso) 145{ 146 struct lima_context *ctx = lima_context(pctx); 147 148 ctx->rasterizer = hwcso; 149 ctx->dirty |= LIMA_CONTEXT_DIRTY_RASTERIZER; 150} 151 152static void 153lima_delete_rasterizer_state(struct pipe_context *pctx, void *hwcso) 154{ 155 FREE(hwcso); 156} 157 158static void * 159lima_create_blend_state(struct pipe_context *pctx, 160 const struct pipe_blend_state *cso) 161{ 162 struct lima_blend_state *so; 163 164 so = CALLOC_STRUCT(lima_blend_state); 165 if (!so) 166 return NULL; 167 168 so->base = *cso; 169 170 return so; 171} 172 173static void 174lima_bind_blend_state(struct pipe_context *pctx, void *hwcso) 175{ 176 struct lima_context *ctx = lima_context(pctx); 177 178 ctx->blend = hwcso; 179 ctx->dirty |= LIMA_CONTEXT_DIRTY_BLEND; 180} 181 182static void 183lima_delete_blend_state(struct pipe_context *pctx, void *hwcso) 184{ 185 FREE(hwcso); 186} 187 188static void * 189lima_create_vertex_elements_state(struct pipe_context *pctx, unsigned num_elements, 190 const struct pipe_vertex_element *elements) 191{ 192 struct lima_vertex_element_state *so; 193 194 so = CALLOC_STRUCT(lima_vertex_element_state); 195 if (!so) 196 return NULL; 197 198 memcpy(so->pipe, elements, sizeof(*elements) * num_elements); 199 so->num_elements = num_elements; 200 201 return so; 202} 203 204static void 205lima_bind_vertex_elements_state(struct pipe_context *pctx, void *hwcso) 206{ 207 struct lima_context *ctx = lima_context(pctx); 208 209 ctx->vertex_elements = hwcso; 210 ctx->dirty |= LIMA_CONTEXT_DIRTY_VERTEX_ELEM; 211} 212 213static void 214lima_delete_vertex_elements_state(struct pipe_context *pctx, void *hwcso) 215{ 216 FREE(hwcso); 217} 218 219static void 220lima_set_vertex_buffers(struct pipe_context *pctx, 221 unsigned start_slot, unsigned count, 222 const struct pipe_vertex_buffer *vb) 223{ 224 struct lima_context *ctx = lima_context(pctx); 225 struct lima_context_vertex_buffer *so = &ctx->vertex_buffers; 226 227 util_set_vertex_buffers_mask(so->vb + start_slot, &so->enabled_mask, 228 vb, start_slot, count); 229 so->count = util_last_bit(so->enabled_mask); 230 231 ctx->dirty |= LIMA_CONTEXT_DIRTY_VERTEX_BUFF; 232} 233 234static void 235lima_set_viewport_states(struct pipe_context *pctx, 236 unsigned start_slot, 237 unsigned num_viewports, 238 const struct pipe_viewport_state *viewport) 239{ 240 struct lima_context *ctx = lima_context(pctx); 241 242 /* reverse calculate the parameter of glViewport */ 243 ctx->viewport.x = viewport->translate[0] - viewport->scale[0]; 244 ctx->viewport.y = fabsf(viewport->translate[1] - fabsf(viewport->scale[1])); 245 ctx->viewport.width = viewport->scale[0] * 2; 246 ctx->viewport.height = fabsf(viewport->scale[1] * 2); 247 248 /* reverse calculate the parameter of glDepthRange */ 249 ctx->viewport.near = viewport->translate[2] - viewport->scale[2]; 250 ctx->viewport.far = viewport->translate[2] + viewport->scale[2]; 251 252 ctx->viewport.transform = *viewport; 253 ctx->dirty |= LIMA_CONTEXT_DIRTY_VIEWPORT; 254} 255 256static void 257lima_set_scissor_states(struct pipe_context *pctx, 258 unsigned start_slot, 259 unsigned num_scissors, 260 const struct pipe_scissor_state *scissor) 261{ 262 struct lima_context *ctx = lima_context(pctx); 263 264 ctx->scissor = *scissor; 265 ctx->dirty |= LIMA_CONTEXT_DIRTY_SCISSOR; 266} 267 268static void 269lima_set_blend_color(struct pipe_context *pctx, 270 const struct pipe_blend_color *blend_color) 271{ 272 struct lima_context *ctx = lima_context(pctx); 273 274 ctx->blend_color = *blend_color; 275 ctx->dirty |= LIMA_CONTEXT_DIRTY_BLEND_COLOR; 276} 277 278static void 279lima_set_stencil_ref(struct pipe_context *pctx, 280 const struct pipe_stencil_ref *stencil_ref) 281{ 282 struct lima_context *ctx = lima_context(pctx); 283 284 ctx->stencil_ref = *stencil_ref; 285 ctx->dirty |= LIMA_CONTEXT_DIRTY_STENCIL_REF; 286} 287 288static void 289lima_set_constant_buffer(struct pipe_context *pctx, 290 enum pipe_shader_type shader, uint index, 291 const struct pipe_constant_buffer *cb) 292{ 293 struct lima_context *ctx = lima_context(pctx); 294 struct lima_context_constant_buffer *so = ctx->const_buffer + shader; 295 296 assert(index == 0); 297 298 if (unlikely(!cb)) { 299 so->buffer = NULL; 300 so->size = 0; 301 } else { 302 assert(!cb->buffer); 303 304 so->buffer = cb->user_buffer + cb->buffer_offset; 305 so->size = cb->buffer_size; 306 } 307 308 so->dirty = true; 309 ctx->dirty |= LIMA_CONTEXT_DIRTY_CONST_BUFF; 310 311} 312 313static void * 314lima_create_sampler_state(struct pipe_context *pctx, 315 const struct pipe_sampler_state *cso) 316{ 317 struct lima_sampler_state *so = CALLOC_STRUCT(lima_sampler_state); 318 if (!so) 319 return NULL; 320 321 memcpy(so, cso, sizeof(*cso)); 322 323 return so; 324} 325 326static void 327lima_sampler_state_delete(struct pipe_context *pctx, void *sstate) 328{ 329 free(sstate); 330} 331 332static void 333lima_sampler_states_bind(struct pipe_context *pctx, 334 enum pipe_shader_type shader, unsigned start, 335 unsigned nr, void **hwcso) 336{ 337 struct lima_context *ctx = lima_context(pctx); 338 struct lima_texture_stateobj *lima_tex = &ctx->tex_stateobj; 339 unsigned i; 340 unsigned new_nr = 0; 341 342 assert(start == 0); 343 344 for (i = 0; i < nr; i++) { 345 if (hwcso[i]) 346 new_nr = i + 1; 347 lima_tex->samplers[i] = hwcso[i]; 348 } 349 350 for (; i < lima_tex->num_samplers; i++) { 351 lima_tex->samplers[i] = NULL; 352 } 353 354 lima_tex->num_samplers = new_nr; 355 ctx->dirty |= LIMA_CONTEXT_DIRTY_TEXTURES; 356} 357 358static struct pipe_sampler_view * 359lima_create_sampler_view(struct pipe_context *pctx, struct pipe_resource *prsc, 360 const struct pipe_sampler_view *cso) 361{ 362 struct lima_sampler_view *so = CALLOC_STRUCT(lima_sampler_view); 363 364 if (!so) 365 return NULL; 366 367 so->base = *cso; 368 369 pipe_reference(NULL, &prsc->reference); 370 so->base.texture = prsc; 371 so->base.reference.count = 1; 372 so->base.context = pctx; 373 374 return &so->base; 375} 376 377static void 378lima_sampler_view_destroy(struct pipe_context *pctx, 379 struct pipe_sampler_view *pview) 380{ 381 struct lima_sampler_view *view = lima_sampler_view(pview); 382 383 pipe_resource_reference(&pview->texture, NULL); 384 385 free(view); 386} 387 388static void 389lima_set_sampler_views(struct pipe_context *pctx, 390 enum pipe_shader_type shader, 391 unsigned start, unsigned nr, 392 struct pipe_sampler_view **views) 393{ 394 struct lima_context *ctx = lima_context(pctx); 395 struct lima_texture_stateobj *lima_tex = &ctx->tex_stateobj; 396 int i; 397 unsigned new_nr = 0; 398 399 assert(start == 0); 400 401 for (i = 0; i < nr; i++) { 402 if (views[i]) 403 new_nr = i + 1; 404 pipe_sampler_view_reference(&lima_tex->textures[i], views[i]); 405 } 406 407 for (; i < lima_tex->num_textures; i++) { 408 pipe_sampler_view_reference(&lima_tex->textures[i], NULL); 409 } 410 411 lima_tex->num_textures = new_nr; 412 ctx->dirty |= LIMA_CONTEXT_DIRTY_TEXTURES; 413} 414 415static boolean 416lima_set_damage_region(struct pipe_context *pctx, unsigned num_rects, int *rects) 417{ 418 struct lima_context *ctx = lima_context(pctx); 419 struct lima_damage_state *damage = &ctx->damage; 420 int i; 421 422 if (damage->region) 423 ralloc_free(damage->region); 424 425 if (!num_rects) { 426 damage->region = NULL; 427 damage->num_region = 0; 428 return true; 429 } 430 431 damage->region = ralloc_size(ctx, sizeof(*damage->region) * num_rects); 432 if (!damage->region) { 433 damage->num_region = 0; 434 return false; 435 } 436 437 for (i = 0; i < num_rects; i++) { 438 struct pipe_scissor_state *r = damage->region + i; 439 /* region in tile unit */ 440 r->minx = rects[i * 4] >> 4; 441 r->miny = rects[i * 4 + 1] >> 4; 442 r->maxx = (rects[i * 4] + rects[i * 4 + 2] + 0xf) >> 4; 443 r->maxy = (rects[i * 4 + 1] + rects[i * 4 + 3] + 0xf) >> 4; 444 } 445 446 /* is region aligned to tiles? */ 447 damage->aligned = true; 448 for (i = 0; i < num_rects * 4; i++) { 449 if (rects[i] & 0xf) { 450 damage->aligned = false; 451 break; 452 } 453 } 454 455 damage->num_region = num_rects; 456 return true; 457} 458 459static void 460lima_set_sample_mask(struct pipe_context *pctx, 461 unsigned sample_mask) 462{ 463} 464 465void 466lima_state_init(struct lima_context *ctx) 467{ 468 ctx->base.set_framebuffer_state = lima_set_framebuffer_state; 469 ctx->base.set_polygon_stipple = lima_set_polygon_stipple; 470 ctx->base.set_viewport_states = lima_set_viewport_states; 471 ctx->base.set_scissor_states = lima_set_scissor_states; 472 ctx->base.set_blend_color = lima_set_blend_color; 473 ctx->base.set_stencil_ref = lima_set_stencil_ref; 474 475 ctx->base.set_vertex_buffers = lima_set_vertex_buffers; 476 ctx->base.set_constant_buffer = lima_set_constant_buffer; 477 478 ctx->base.create_depth_stencil_alpha_state = lima_create_depth_stencil_alpha_state; 479 ctx->base.bind_depth_stencil_alpha_state = lima_bind_depth_stencil_alpha_state; 480 ctx->base.delete_depth_stencil_alpha_state = lima_delete_depth_stencil_alpha_state; 481 482 ctx->base.create_rasterizer_state = lima_create_rasterizer_state; 483 ctx->base.bind_rasterizer_state = lima_bind_rasterizer_state; 484 ctx->base.delete_rasterizer_state = lima_delete_rasterizer_state; 485 486 ctx->base.create_blend_state = lima_create_blend_state; 487 ctx->base.bind_blend_state = lima_bind_blend_state; 488 ctx->base.delete_blend_state = lima_delete_blend_state; 489 490 ctx->base.create_vertex_elements_state = lima_create_vertex_elements_state; 491 ctx->base.bind_vertex_elements_state = lima_bind_vertex_elements_state; 492 ctx->base.delete_vertex_elements_state = lima_delete_vertex_elements_state; 493 494 ctx->base.create_sampler_state = lima_create_sampler_state; 495 ctx->base.delete_sampler_state = lima_sampler_state_delete; 496 ctx->base.bind_sampler_states = lima_sampler_states_bind; 497 498 ctx->base.create_sampler_view = lima_create_sampler_view; 499 ctx->base.sampler_view_destroy = lima_sampler_view_destroy; 500 ctx->base.set_sampler_views = lima_set_sampler_views; 501 502 ctx->base.set_sample_mask = lima_set_sample_mask; 503} 504 505void 506lima_state_fini(struct lima_context *ctx) 507{ 508 struct lima_context_vertex_buffer *so = &ctx->vertex_buffers; 509 510 util_set_vertex_buffers_mask(so->vb, &so->enabled_mask, NULL, 511 0, ARRAY_SIZE(so->vb)); 512 513 pipe_surface_reference(&ctx->framebuffer.base.cbufs[0], NULL); 514 pipe_surface_reference(&ctx->framebuffer.base.zsbuf, NULL); 515} 516