i915_gem_render_state.c revision 46470fc932ac8a0e8317a220b3f4ea4ed903338e
1/* 2 * Copyright © 2014 Intel Corporation 3 * 4 * Permission is hereby granted, free of charge, to any person obtaining a 5 * copy of this software and associated documentation files (the "Software"), 6 * to deal in the Software without restriction, including without limitation 7 * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8 * and/or sell copies of the Software, and to permit persons to whom the 9 * Software is furnished to do so, subject to the following conditions: 10 * 11 * The above copyright notice and this permission notice (including the next 12 * paragraph) shall be included in all copies or substantial portions of the 13 * Software. 14 * 15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 18 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 20 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 21 * IN THE SOFTWARE. 22 * 23 * Authors: 24 * Mika Kuoppala <mika.kuoppala@intel.com> 25 * 26 */ 27 28#include "i915_drv.h" 29#include "intel_renderstate.h" 30 31struct i915_render_state { 32 struct drm_i915_gem_object *obj; 33 unsigned long ggtt_offset; 34 void *batch; 35 u32 size; 36 u32 len; 37}; 38 39static struct i915_render_state *render_state_alloc(struct drm_device *dev) 40{ 41 struct i915_render_state *so; 42 struct page *page; 43 int ret; 44 45 so = kzalloc(sizeof(*so), GFP_KERNEL); 46 if (!so) 47 return ERR_PTR(-ENOMEM); 48 49 so->obj = i915_gem_alloc_object(dev, 4096); 50 if (so->obj == NULL) { 51 ret = -ENOMEM; 52 goto free; 53 } 54 so->size = 4096; 55 56 ret = i915_gem_obj_ggtt_pin(so->obj, 4096, 0); 57 if (ret) 58 goto free_gem; 59 60 BUG_ON(so->obj->pages->nents != 1); 61 page = sg_page(so->obj->pages->sgl); 62 63 so->batch = kmap(page); 64 if (!so->batch) { 65 ret = -ENOMEM; 66 goto unpin; 67 } 68 69 so->ggtt_offset = i915_gem_obj_ggtt_offset(so->obj); 70 71 return so; 72unpin: 73 i915_gem_object_ggtt_unpin(so->obj); 74free_gem: 75 drm_gem_object_unreference(&so->obj->base); 76free: 77 kfree(so); 78 return ERR_PTR(ret); 79} 80 81static void render_state_free(struct i915_render_state *so) 82{ 83 kunmap(so->batch); 84 i915_gem_object_ggtt_unpin(so->obj); 85 drm_gem_object_unreference(&so->obj->base); 86 kfree(so); 87} 88 89static const struct intel_renderstate_rodata * 90render_state_get_rodata(struct drm_device *dev, const int gen) 91{ 92 switch (gen) { 93 case 6: 94 return &gen6_null_state; 95 case 7: 96 return &gen7_null_state; 97 case 8: 98 return &gen8_null_state; 99 } 100 101 return NULL; 102} 103 104static int render_state_setup(const int gen, 105 const struct intel_renderstate_rodata *rodata, 106 struct i915_render_state *so) 107{ 108 const u64 goffset = i915_gem_obj_ggtt_offset(so->obj); 109 u32 reloc_index = 0; 110 u32 * const d = so->batch; 111 unsigned int i = 0; 112 int ret; 113 114 if (!rodata || rodata->batch_items * 4 > so->size) 115 return -EINVAL; 116 117 ret = i915_gem_object_set_to_cpu_domain(so->obj, true); 118 if (ret) 119 return ret; 120 121 while (i < rodata->batch_items) { 122 u32 s = rodata->batch[i]; 123 124 if (reloc_index < rodata->reloc_items && 125 i * 4 == rodata->reloc[reloc_index]) { 126 127 s += goffset & 0xffffffff; 128 129 /* We keep batch offsets max 32bit */ 130 if (gen >= 8) { 131 if (i + 1 >= rodata->batch_items || 132 rodata->batch[i + 1] != 0) 133 return -EINVAL; 134 135 d[i] = s; 136 i++; 137 s = (goffset & 0xffffffff00000000ull) >> 32; 138 } 139 140 reloc_index++; 141 } 142 143 d[i] = s; 144 i++; 145 } 146 147 ret = i915_gem_object_set_to_gtt_domain(so->obj, false); 148 if (ret) 149 return ret; 150 151 if (rodata->reloc_items != reloc_index) { 152 DRM_ERROR("not all relocs resolved, %d out of %d\n", 153 reloc_index, rodata->reloc_items); 154 return -EINVAL; 155 } 156 157 so->len = rodata->batch_items * 4; 158 159 return 0; 160} 161 162int i915_gem_render_state_init(struct intel_ring_buffer *ring) 163{ 164 const int gen = INTEL_INFO(ring->dev)->gen; 165 struct i915_render_state *so; 166 const struct intel_renderstate_rodata *rodata; 167 int ret; 168 169 if (WARN_ON(ring->id != RCS)) 170 return -ENOENT; 171 172 rodata = render_state_get_rodata(ring->dev, gen); 173 if (rodata == NULL) 174 return 0; 175 176 so = render_state_alloc(ring->dev); 177 if (IS_ERR(so)) 178 return PTR_ERR(so); 179 180 ret = render_state_setup(gen, rodata, so); 181 if (ret) 182 goto out; 183 184 ret = ring->dispatch_execbuffer(ring, 185 i915_gem_obj_ggtt_offset(so->obj), 186 so->len, 187 I915_DISPATCH_SECURE); 188 if (ret) 189 goto out; 190 191 i915_vma_move_to_active(i915_gem_obj_to_ggtt(so->obj), ring); 192 193 ret = __i915_add_request(ring, NULL, so->obj, NULL); 194 /* __i915_add_request moves object to inactive if it fails */ 195out: 196 render_state_free(so); 197 return ret; 198} 199