142542f5fSchristos/* 242542f5fSchristos * Copyright © 2012 Intel Corporation 342542f5fSchristos * 442542f5fSchristos * Permission is hereby granted, free of charge, to any person obtaining a 542542f5fSchristos * copy of this software and associated documentation files (the "Software"), 642542f5fSchristos * to deal in the Software without restriction, including without limitation 742542f5fSchristos * the rights to use, copy, modify, merge, publish, distribute, sublicense, 842542f5fSchristos * and/or sell copies of the Software, and to permit persons to whom the 942542f5fSchristos * Software is furnished to do so, subject to the following conditions: 1042542f5fSchristos * 1142542f5fSchristos * The above copyright notice and this permission notice (including the next 1242542f5fSchristos * paragraph) shall be included in all copies or substantial portions of the 1342542f5fSchristos * Software. 1442542f5fSchristos * 1542542f5fSchristos * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 1642542f5fSchristos * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 1742542f5fSchristos * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 1842542f5fSchristos * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 1942542f5fSchristos * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 2042542f5fSchristos * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 2142542f5fSchristos * SOFTWARE. 2242542f5fSchristos * 2342542f5fSchristos * Authors: 2442542f5fSchristos * Chris Wilson <chris@chris-wilson.co.uk> 2542542f5fSchristos * 2642542f5fSchristos */ 2742542f5fSchristos 2842542f5fSchristos#ifdef HAVE_CONFIG_H 2942542f5fSchristos#include "config.h" 3042542f5fSchristos#endif 3142542f5fSchristos 3242542f5fSchristos#include "sna.h" 3342542f5fSchristos#include "sna_render.h" 3442542f5fSchristos#include "sna_render_inline.h" 3542542f5fSchristos#include "gen8_vertex.h" 3642542f5fSchristos 3742542f5fSchristosvoid gen8_vertex_align(struct sna *sna, const struct sna_composite_op *op) 3842542f5fSchristos{ 3942542f5fSchristos int vertex_index; 4042542f5fSchristos 4142542f5fSchristos assert(op->floats_per_rect == 3*op->floats_per_vertex); 4242542f5fSchristos 4342542f5fSchristos vertex_index = (sna->render.vertex_used + op->floats_per_vertex - 1) / op->floats_per_vertex; 4442542f5fSchristos if ((int)sna->render.vertex_size - vertex_index * op->floats_per_vertex < 2*op->floats_per_rect) { 4542542f5fSchristos DBG(("%s: flushing vertex buffer: new index=%d, max=%d\n", 4642542f5fSchristos __FUNCTION__, vertex_index, sna->render.vertex_size / op->floats_per_vertex)); 4742542f5fSchristos if (gen8_vertex_finish(sna) < 2*op->floats_per_rect) { 4842542f5fSchristos kgem_submit(&sna->kgem); 4942542f5fSchristos _kgem_set_mode(&sna->kgem, KGEM_RENDER); 5042542f5fSchristos } 5142542f5fSchristos 5242542f5fSchristos vertex_index = (sna->render.vertex_used + op->floats_per_vertex - 1) / op->floats_per_vertex; 5342542f5fSchristos assert(vertex_index * op->floats_per_vertex <= sna->render.vertex_size); 5442542f5fSchristos } 5542542f5fSchristos 5642542f5fSchristos sna->render.vertex_index = vertex_index; 5742542f5fSchristos sna->render.vertex_used = vertex_index * op->floats_per_vertex; 5842542f5fSchristos} 5942542f5fSchristos 6042542f5fSchristosvoid gen8_vertex_flush(struct sna *sna) 6142542f5fSchristos{ 6242542f5fSchristos DBG(("%s[%x] = %d\n", __FUNCTION__, 6342542f5fSchristos 4*sna->render.vertex_offset, 6442542f5fSchristos sna->render.vertex_index - sna->render.vertex_start)); 6542542f5fSchristos 6642542f5fSchristos assert(sna->render.vertex_offset); 6742542f5fSchristos assert(sna->render.vertex_offset <= sna->kgem.nbatch); 6842542f5fSchristos assert(sna->render.vertex_index > sna->render.vertex_start); 6942542f5fSchristos assert(sna->render.vertex_used <= sna->render.vertex_size); 7042542f5fSchristos 7142542f5fSchristos sna->kgem.batch[sna->render.vertex_offset] = 7242542f5fSchristos sna->render.vertex_index - sna->render.vertex_start; 7342542f5fSchristos sna->render.vertex_offset = 0; 7442542f5fSchristos} 7542542f5fSchristos 7642542f5fSchristosint gen8_vertex_finish(struct sna *sna) 7742542f5fSchristos{ 7842542f5fSchristos struct kgem_bo *bo; 7942542f5fSchristos unsigned int i; 8042542f5fSchristos unsigned hint, size; 8142542f5fSchristos 8242542f5fSchristos DBG(("%s: used=%d / %d\n", __FUNCTION__, 8342542f5fSchristos sna->render.vertex_used, sna->render.vertex_size)); 8442542f5fSchristos assert(sna->render.vertex_offset == 0); 8542542f5fSchristos assert(sna->render.vertex_used); 8642542f5fSchristos assert(sna->render.vertex_used <= sna->render.vertex_size); 8742542f5fSchristos 8842542f5fSchristos sna_vertex_wait__locked(&sna->render); 8942542f5fSchristos 9042542f5fSchristos /* Note: we only need dword alignment (currently) */ 9142542f5fSchristos 9242542f5fSchristos hint = CREATE_GTT_MAP; 9342542f5fSchristos 9442542f5fSchristos bo = sna->render.vbo; 9542542f5fSchristos if (bo) { 9642542f5fSchristos for (i = 0; i < sna->render.nvertex_reloc; i++) { 9742542f5fSchristos DBG(("%s: reloc[%d] = %d\n", __FUNCTION__, 9842542f5fSchristos i, sna->render.vertex_reloc[i])); 9942542f5fSchristos 10042542f5fSchristos *(uint64_t *)(sna->kgem.batch+sna->render.vertex_reloc[i]) = 10142542f5fSchristos kgem_add_reloc64(&sna->kgem, 10242542f5fSchristos sna->render.vertex_reloc[i], bo, 10342542f5fSchristos I915_GEM_DOMAIN_VERTEX << 16, 10442542f5fSchristos 0); 10542542f5fSchristos } 10642542f5fSchristos 10742542f5fSchristos assert(!sna->render.active); 10842542f5fSchristos sna->render.nvertex_reloc = 0; 10942542f5fSchristos sna->render.vertex_used = 0; 11042542f5fSchristos sna->render.vertex_index = 0; 11142542f5fSchristos sna->render.vbo = NULL; 11242542f5fSchristos sna->render.vb_id = 0; 11342542f5fSchristos 11442542f5fSchristos kgem_bo_destroy(&sna->kgem, bo); 11542542f5fSchristos hint |= CREATE_CACHED | CREATE_NO_THROTTLE; 11642542f5fSchristos } else { 11742542f5fSchristos if (kgem_is_idle(&sna->kgem)) { 11842542f5fSchristos sna->render.vertices = sna->render.vertex_data; 11942542f5fSchristos sna->render.vertex_size = ARRAY_SIZE(sna->render.vertex_data); 12042542f5fSchristos return 0; 12142542f5fSchristos } 12242542f5fSchristos } 12342542f5fSchristos 12442542f5fSchristos size = 256*1024; 12542542f5fSchristos assert(!sna->render.active); 12642542f5fSchristos sna->render.vertices = NULL; 12742542f5fSchristos sna->render.vbo = kgem_create_linear(&sna->kgem, size, hint); 12842542f5fSchristos while (sna->render.vbo == NULL && size > 16*1024) { 12942542f5fSchristos size /= 2; 13042542f5fSchristos sna->render.vbo = kgem_create_linear(&sna->kgem, size, hint); 13142542f5fSchristos } 13242542f5fSchristos if (sna->render.vbo == NULL) 13342542f5fSchristos sna->render.vbo = kgem_create_linear(&sna->kgem, 13442542f5fSchristos 256*1024, CREATE_GTT_MAP); 13542542f5fSchristos if (sna->render.vbo) 13642542f5fSchristos sna->render.vertices = kgem_bo_map(&sna->kgem, sna->render.vbo); 13742542f5fSchristos if (sna->render.vertices == NULL) { 13842542f5fSchristos if (sna->render.vbo) { 13942542f5fSchristos kgem_bo_destroy(&sna->kgem, sna->render.vbo); 14042542f5fSchristos sna->render.vbo = NULL; 14142542f5fSchristos } 14242542f5fSchristos sna->render.vertices = sna->render.vertex_data; 14342542f5fSchristos sna->render.vertex_size = ARRAY_SIZE(sna->render.vertex_data); 14442542f5fSchristos return 0; 14542542f5fSchristos } 14642542f5fSchristos 14742542f5fSchristos if (sna->render.vertex_used) { 14842542f5fSchristos DBG(("%s: copying initial buffer x %d to handle=%d\n", 14942542f5fSchristos __FUNCTION__, 15042542f5fSchristos sna->render.vertex_used, 15142542f5fSchristos sna->render.vbo->handle)); 15242542f5fSchristos assert(sizeof(float)*sna->render.vertex_used <= 15342542f5fSchristos __kgem_bo_size(sna->render.vbo)); 15442542f5fSchristos memcpy(sna->render.vertices, 15542542f5fSchristos sna->render.vertex_data, 15642542f5fSchristos sizeof(float)*sna->render.vertex_used); 15742542f5fSchristos } 15842542f5fSchristos 15942542f5fSchristos size = __kgem_bo_size(sna->render.vbo)/4; 16042542f5fSchristos if (size >= UINT16_MAX) 16142542f5fSchristos size = UINT16_MAX - 1; 16242542f5fSchristos 16342542f5fSchristos DBG(("%s: create vbo handle=%d, size=%d\n", 16442542f5fSchristos __FUNCTION__, sna->render.vbo->handle, size)); 16542542f5fSchristos 16642542f5fSchristos sna->render.vertex_size = size; 16742542f5fSchristos return sna->render.vertex_size - sna->render.vertex_used; 16842542f5fSchristos} 16942542f5fSchristos 17042542f5fSchristosvoid gen8_vertex_close(struct sna *sna) 17142542f5fSchristos{ 17242542f5fSchristos struct kgem_bo *bo, *free_bo = NULL; 17342542f5fSchristos unsigned int i, delta = 0; 17442542f5fSchristos 17542542f5fSchristos assert(sna->render.vertex_offset == 0); 17642542f5fSchristos if (!sna->render.vb_id) 17742542f5fSchristos return; 17842542f5fSchristos 17942542f5fSchristos DBG(("%s: used=%d, vbo active? %d, vb=%x, nreloc=%d\n", 18042542f5fSchristos __FUNCTION__, sna->render.vertex_used, sna->render.vbo ? sna->render.vbo->handle : 0, 18142542f5fSchristos sna->render.vb_id, sna->render.nvertex_reloc)); 18242542f5fSchristos 18342542f5fSchristos assert(!sna->render.active); 18442542f5fSchristos 18542542f5fSchristos bo = sna->render.vbo; 18642542f5fSchristos if (bo) { 18742542f5fSchristos if (sna->render.vertex_size - sna->render.vertex_used < 64) { 18842542f5fSchristos DBG(("%s: discarding vbo (full), handle=%d\n", __FUNCTION__, sna->render.vbo->handle)); 18942542f5fSchristos sna->render.vbo = NULL; 19042542f5fSchristos sna->render.vertices = sna->render.vertex_data; 19142542f5fSchristos sna->render.vertex_size = ARRAY_SIZE(sna->render.vertex_data); 19242542f5fSchristos free_bo = bo; 19342542f5fSchristos } else if (!sna->kgem.has_llc && sna->render.vertices == MAP(bo->map__cpu)) { 19442542f5fSchristos DBG(("%s: converting CPU map to GTT\n", __FUNCTION__)); 19542542f5fSchristos sna->render.vertices = 19642542f5fSchristos kgem_bo_map__gtt(&sna->kgem, sna->render.vbo); 19742542f5fSchristos if (sna->render.vertices == NULL) { 19842542f5fSchristos sna->render.vbo = NULL; 19942542f5fSchristos sna->render.vertices = sna->render.vertex_data; 20042542f5fSchristos sna->render.vertex_size = ARRAY_SIZE(sna->render.vertex_data); 20142542f5fSchristos free_bo = bo; 20242542f5fSchristos } 20342542f5fSchristos 20442542f5fSchristos } 20542542f5fSchristos } else { 20642542f5fSchristos int size; 20742542f5fSchristos 20842542f5fSchristos size = sna->kgem.nbatch; 20942542f5fSchristos size += sna->kgem.batch_size - sna->kgem.surface; 21042542f5fSchristos size += sna->render.vertex_used; 21142542f5fSchristos 21242542f5fSchristos if (size <= 1024) { 21342542f5fSchristos DBG(("%s: copy to batch: %d @ %d\n", __FUNCTION__, 21442542f5fSchristos sna->render.vertex_used, sna->kgem.nbatch)); 21542542f5fSchristos assert(sna->kgem.nbatch + sna->render.vertex_used <= sna->kgem.surface); 21642542f5fSchristos memcpy(sna->kgem.batch + sna->kgem.nbatch, 21742542f5fSchristos sna->render.vertex_data, 21842542f5fSchristos sna->render.vertex_used * 4); 21942542f5fSchristos delta = sna->kgem.nbatch * 4; 22042542f5fSchristos bo = NULL; 22142542f5fSchristos sna->kgem.nbatch += sna->render.vertex_used; 22242542f5fSchristos } else { 22342542f5fSchristos size = 256 * 1024; 22442542f5fSchristos do { 22542542f5fSchristos bo = kgem_create_linear(&sna->kgem, size, 22642542f5fSchristos CREATE_GTT_MAP | CREATE_NO_RETIRE | CREATE_NO_THROTTLE | CREATE_CACHED); 22742542f5fSchristos } while (bo == NULL && (size>>=1) > sizeof(float)*sna->render.vertex_used); 22842542f5fSchristos 22942542f5fSchristos sna->render.vertices = NULL; 23042542f5fSchristos if (bo) 23142542f5fSchristos sna->render.vertices = kgem_bo_map(&sna->kgem, bo); 23242542f5fSchristos if (sna->render.vertices != NULL) { 23342542f5fSchristos DBG(("%s: new vbo: %d / %d\n", __FUNCTION__, 23442542f5fSchristos sna->render.vertex_used, __kgem_bo_size(bo)/4)); 23542542f5fSchristos 23642542f5fSchristos assert(sizeof(float)*sna->render.vertex_used <= __kgem_bo_size(bo)); 23742542f5fSchristos memcpy(sna->render.vertices, 23842542f5fSchristos sna->render.vertex_data, 23942542f5fSchristos sizeof(float)*sna->render.vertex_used); 24042542f5fSchristos 24142542f5fSchristos size = __kgem_bo_size(bo)/4; 24242542f5fSchristos if (size >= UINT16_MAX) 24342542f5fSchristos size = UINT16_MAX - 1; 24442542f5fSchristos 24542542f5fSchristos sna->render.vbo = bo; 24642542f5fSchristos sna->render.vertex_size = size; 24742542f5fSchristos } else { 24842542f5fSchristos DBG(("%s: tmp vbo: %d\n", __FUNCTION__, 24942542f5fSchristos sna->render.vertex_used)); 25042542f5fSchristos 25142542f5fSchristos if (bo) 25242542f5fSchristos kgem_bo_destroy(&sna->kgem, bo); 25342542f5fSchristos 25442542f5fSchristos bo = kgem_create_linear(&sna->kgem, 25542542f5fSchristos 4*sna->render.vertex_used, 25642542f5fSchristos CREATE_NO_THROTTLE); 25742542f5fSchristos if (bo && !kgem_bo_write(&sna->kgem, bo, 25842542f5fSchristos sna->render.vertex_data, 25942542f5fSchristos 4*sna->render.vertex_used)) { 26042542f5fSchristos kgem_bo_destroy(&sna->kgem, bo); 26142542f5fSchristos bo = NULL; 26242542f5fSchristos } 26342542f5fSchristos 26442542f5fSchristos assert(sna->render.vbo == NULL); 26542542f5fSchristos sna->render.vertices = sna->render.vertex_data; 26642542f5fSchristos sna->render.vertex_size = ARRAY_SIZE(sna->render.vertex_data); 26742542f5fSchristos free_bo = bo; 26842542f5fSchristos } 26942542f5fSchristos } 27042542f5fSchristos } 27142542f5fSchristos 27242542f5fSchristos assert(sna->render.nvertex_reloc); 27342542f5fSchristos for (i = 0; i < sna->render.nvertex_reloc; i++) { 27442542f5fSchristos DBG(("%s: reloc[%d] = %d\n", __FUNCTION__, 27542542f5fSchristos i, sna->render.vertex_reloc[i])); 27642542f5fSchristos 27742542f5fSchristos *(uint64_t *)(sna->kgem.batch+sna->render.vertex_reloc[i]) = 27842542f5fSchristos kgem_add_reloc64(&sna->kgem, 27942542f5fSchristos sna->render.vertex_reloc[i], bo, 28042542f5fSchristos I915_GEM_DOMAIN_VERTEX << 16, 28142542f5fSchristos delta); 28242542f5fSchristos } 28342542f5fSchristos sna->render.nvertex_reloc = 0; 28442542f5fSchristos sna->render.vb_id = 0; 28542542f5fSchristos 28642542f5fSchristos if (sna->render.vbo == NULL) { 28742542f5fSchristos assert(!sna->render.active); 28842542f5fSchristos sna->render.vertex_used = 0; 28942542f5fSchristos sna->render.vertex_index = 0; 29042542f5fSchristos assert(sna->render.vertices == sna->render.vertex_data); 29142542f5fSchristos assert(sna->render.vertex_size == ARRAY_SIZE(sna->render.vertex_data)); 29242542f5fSchristos } 29342542f5fSchristos 29442542f5fSchristos if (free_bo) 29542542f5fSchristos kgem_bo_destroy(&sna->kgem, free_bo); 29642542f5fSchristos} 297