1/*
2 * Copyright © 2007 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 *    Eric Anholt <eric@anholt.net>
25 *
26 */
27
28#ifdef HAVE_CONFIG_H
29#include "config.h"
30#endif
31
32#include <string.h>
33#include <stdlib.h>
34#include <stdint.h>
35#include <assert.h>
36#include <errno.h>
37#include <drm.h>
38#include <i915_drm.h>
39#ifndef __ANDROID__
40#include <pciaccess.h>
41#endif
42#include "libdrm_macros.h"
43#include "intel_bufmgr.h"
44#include "intel_bufmgr_priv.h"
45#include "xf86drm.h"
46
47/** @file intel_bufmgr.c
48 *
49 * Convenience functions for buffer management methods.
50 */
51
52drm_intel_bo *
53drm_intel_bo_alloc(drm_intel_bufmgr *bufmgr, const char *name,
54		   unsigned long size, unsigned int alignment)
55{
56	return bufmgr->bo_alloc(bufmgr, name, size, alignment);
57}
58
59drm_intel_bo *
60drm_intel_bo_alloc_for_render(drm_intel_bufmgr *bufmgr, const char *name,
61			      unsigned long size, unsigned int alignment)
62{
63	return bufmgr->bo_alloc_for_render(bufmgr, name, size, alignment);
64}
65
66drm_intel_bo *
67drm_intel_bo_alloc_userptr(drm_intel_bufmgr *bufmgr,
68			   const char *name, void *addr,
69			   uint32_t tiling_mode,
70			   uint32_t stride,
71			   unsigned long size,
72			   unsigned long flags)
73{
74	if (bufmgr->bo_alloc_userptr)
75		return bufmgr->bo_alloc_userptr(bufmgr, name, addr, tiling_mode,
76						stride, size, flags);
77	return NULL;
78}
79
80drm_intel_bo *
81drm_intel_bo_alloc_tiled(drm_intel_bufmgr *bufmgr, const char *name,
82                        int x, int y, int cpp, uint32_t *tiling_mode,
83                        unsigned long *pitch, unsigned long flags)
84{
85	return bufmgr->bo_alloc_tiled(bufmgr, name, x, y, cpp,
86				      tiling_mode, pitch, flags);
87}
88
89void
90drm_intel_bo_reference(drm_intel_bo *bo)
91{
92	bo->bufmgr->bo_reference(bo);
93}
94
95void
96drm_intel_bo_unreference(drm_intel_bo *bo)
97{
98	if (bo == NULL)
99		return;
100
101	bo->bufmgr->bo_unreference(bo);
102}
103
104int
105drm_intel_bo_map(drm_intel_bo *buf, int write_enable)
106{
107	return buf->bufmgr->bo_map(buf, write_enable);
108}
109
110int
111drm_intel_bo_unmap(drm_intel_bo *buf)
112{
113	return buf->bufmgr->bo_unmap(buf);
114}
115
116int
117drm_intel_bo_subdata(drm_intel_bo *bo, unsigned long offset,
118		     unsigned long size, const void *data)
119{
120	return bo->bufmgr->bo_subdata(bo, offset, size, data);
121}
122
123int
124drm_intel_bo_get_subdata(drm_intel_bo *bo, unsigned long offset,
125			 unsigned long size, void *data)
126{
127	int ret;
128	if (bo->bufmgr->bo_get_subdata)
129		return bo->bufmgr->bo_get_subdata(bo, offset, size, data);
130
131	if (size == 0 || data == NULL)
132		return 0;
133
134	ret = drm_intel_bo_map(bo, 0);
135	if (ret)
136		return ret;
137	memcpy(data, (unsigned char *)bo->virtual + offset, size);
138	drm_intel_bo_unmap(bo);
139	return 0;
140}
141
142void
143drm_intel_bo_wait_rendering(drm_intel_bo *bo)
144{
145	bo->bufmgr->bo_wait_rendering(bo);
146}
147
148void
149drm_intel_bufmgr_destroy(drm_intel_bufmgr *bufmgr)
150{
151	bufmgr->destroy(bufmgr);
152}
153
154int
155drm_intel_bo_exec(drm_intel_bo *bo, int used,
156		  drm_clip_rect_t * cliprects, int num_cliprects, int DR4)
157{
158	return bo->bufmgr->bo_exec(bo, used, cliprects, num_cliprects, DR4);
159}
160
161int
162drm_intel_bo_mrb_exec(drm_intel_bo *bo, int used,
163		drm_clip_rect_t *cliprects, int num_cliprects, int DR4,
164		unsigned int rings)
165{
166	if (bo->bufmgr->bo_mrb_exec)
167		return bo->bufmgr->bo_mrb_exec(bo, used,
168					cliprects, num_cliprects, DR4,
169					rings);
170
171	switch (rings) {
172	case I915_EXEC_DEFAULT:
173	case I915_EXEC_RENDER:
174		return bo->bufmgr->bo_exec(bo, used,
175					   cliprects, num_cliprects, DR4);
176	default:
177		return -ENODEV;
178	}
179}
180
181void
182drm_intel_bufmgr_set_debug(drm_intel_bufmgr *bufmgr, int enable_debug)
183{
184	bufmgr->debug = enable_debug;
185}
186
187int
188drm_intel_bufmgr_check_aperture_space(drm_intel_bo ** bo_array, int count)
189{
190	return bo_array[0]->bufmgr->check_aperture_space(bo_array, count);
191}
192
193int
194drm_intel_bo_flink(drm_intel_bo *bo, uint32_t * name)
195{
196	if (bo->bufmgr->bo_flink)
197		return bo->bufmgr->bo_flink(bo, name);
198
199	return -ENODEV;
200}
201
202int
203drm_intel_bo_emit_reloc(drm_intel_bo *bo, uint32_t offset,
204			drm_intel_bo *target_bo, uint32_t target_offset,
205			uint32_t read_domains, uint32_t write_domain)
206{
207	return bo->bufmgr->bo_emit_reloc(bo, offset,
208					 target_bo, target_offset,
209					 read_domains, write_domain);
210}
211
212/* For fence registers, not GL fences */
213int
214drm_intel_bo_emit_reloc_fence(drm_intel_bo *bo, uint32_t offset,
215			      drm_intel_bo *target_bo, uint32_t target_offset,
216			      uint32_t read_domains, uint32_t write_domain)
217{
218	return bo->bufmgr->bo_emit_reloc_fence(bo, offset,
219					       target_bo, target_offset,
220					       read_domains, write_domain);
221}
222
223
224int
225drm_intel_bo_pin(drm_intel_bo *bo, uint32_t alignment)
226{
227	if (bo->bufmgr->bo_pin)
228		return bo->bufmgr->bo_pin(bo, alignment);
229
230	return -ENODEV;
231}
232
233int
234drm_intel_bo_unpin(drm_intel_bo *bo)
235{
236	if (bo->bufmgr->bo_unpin)
237		return bo->bufmgr->bo_unpin(bo);
238
239	return -ENODEV;
240}
241
242int
243drm_intel_bo_set_tiling(drm_intel_bo *bo, uint32_t * tiling_mode,
244			uint32_t stride)
245{
246	if (bo->bufmgr->bo_set_tiling)
247		return bo->bufmgr->bo_set_tiling(bo, tiling_mode, stride);
248
249	*tiling_mode = I915_TILING_NONE;
250	return 0;
251}
252
253int
254drm_intel_bo_get_tiling(drm_intel_bo *bo, uint32_t * tiling_mode,
255			uint32_t * swizzle_mode)
256{
257	if (bo->bufmgr->bo_get_tiling)
258		return bo->bufmgr->bo_get_tiling(bo, tiling_mode, swizzle_mode);
259
260	*tiling_mode = I915_TILING_NONE;
261	*swizzle_mode = I915_BIT_6_SWIZZLE_NONE;
262	return 0;
263}
264
265int
266drm_intel_bo_set_softpin_offset(drm_intel_bo *bo, uint64_t offset)
267{
268	if (bo->bufmgr->bo_set_softpin_offset)
269		return bo->bufmgr->bo_set_softpin_offset(bo, offset);
270
271	return -ENODEV;
272}
273
274int
275drm_intel_bo_disable_reuse(drm_intel_bo *bo)
276{
277	if (bo->bufmgr->bo_disable_reuse)
278		return bo->bufmgr->bo_disable_reuse(bo);
279	return 0;
280}
281
282int
283drm_intel_bo_is_reusable(drm_intel_bo *bo)
284{
285	if (bo->bufmgr->bo_is_reusable)
286		return bo->bufmgr->bo_is_reusable(bo);
287	return 0;
288}
289
290int
291drm_intel_bo_busy(drm_intel_bo *bo)
292{
293	if (bo->bufmgr->bo_busy)
294		return bo->bufmgr->bo_busy(bo);
295	return 0;
296}
297
298int
299drm_intel_bo_madvise(drm_intel_bo *bo, int madv)
300{
301	if (bo->bufmgr->bo_madvise)
302		return bo->bufmgr->bo_madvise(bo, madv);
303	return -1;
304}
305
306int
307drm_intel_bo_use_48b_address_range(drm_intel_bo *bo, uint32_t enable)
308{
309	if (bo->bufmgr->bo_use_48b_address_range) {
310		bo->bufmgr->bo_use_48b_address_range(bo, enable);
311		return 0;
312	}
313
314	return -ENODEV;
315}
316
317int
318drm_intel_bo_references(drm_intel_bo *bo, drm_intel_bo *target_bo)
319{
320	return bo->bufmgr->bo_references(bo, target_bo);
321}
322
323int
324drm_intel_get_pipe_from_crtc_id(drm_intel_bufmgr *bufmgr, int crtc_id)
325{
326	if (bufmgr->get_pipe_from_crtc_id)
327		return bufmgr->get_pipe_from_crtc_id(bufmgr, crtc_id);
328	return -1;
329}
330
331#ifndef __ANDROID__
332static size_t
333drm_intel_probe_agp_aperture_size(int fd)
334{
335	struct pci_device *pci_dev;
336	size_t size = 0;
337	int ret;
338
339	ret = pci_system_init();
340	if (ret)
341		goto err;
342
343	/* XXX handle multiple adaptors? */
344	pci_dev = pci_device_find_by_slot(0, 0, 2, 0);
345	if (pci_dev == NULL)
346		goto err;
347
348	ret = pci_device_probe(pci_dev);
349	if (ret)
350		goto err;
351
352	size = pci_dev->regions[2].size;
353err:
354	pci_system_cleanup ();
355	return size;
356}
357#else
358static size_t
359drm_intel_probe_agp_aperture_size(int fd)
360{
361	/* Nothing seems to rely on this value on Android anyway... */
362	fprintf(stderr, "%s: Mappable aperture size hardcoded to 64MiB\n");
363	return 64 * 1024 * 1024;
364}
365#endif
366
367int
368drm_intel_get_aperture_sizes(int fd, size_t *mappable, size_t *total)
369{
370
371	struct drm_i915_gem_get_aperture aperture;
372	int ret;
373
374	ret = drmIoctl(fd, DRM_IOCTL_I915_GEM_GET_APERTURE, &aperture);
375	if (ret)
376		return ret;
377
378	*mappable = 0;
379	/* XXX add a query for the kernel value? */
380	if (*mappable == 0)
381		*mappable = drm_intel_probe_agp_aperture_size(fd);
382	if (*mappable == 0)
383		*mappable = 64 * 1024 * 1024; /* minimum possible value */
384	*total = aperture.aper_size;
385	return 0;
386}
387