2 #include "intel_be_device.h"
4 #include "pipe/internal/p_winsys_screen.h"
5 #include "pipe/p_defines.h"
6 #include "pipe/p_state.h"
7 #include "pipe/p_inlines.h"
8 #include "util/u_memory.h"
9 #include "util/u_debug.h"
10 #include "util/u_math.h"
12 #include "intel_be_fence.h"
14 #include "i915simple/i915_winsys.h"
15 #include "softpipe/sp_winsys.h"
17 #include "intel_be_api.h"
20 #define I915_TILING_X 1
27 intel_be_buffer_map(struct pipe_winsys
*winsys
,
28 struct pipe_buffer
*buf
,
31 struct intel_be_buffer
*buffer
= intel_be_buffer(buf
);
32 drm_intel_bo
*bo
= intel_bo(buf
);
36 if (flags
& PIPE_BUFFER_USAGE_DONTBLOCK
) {
37 /* Remove this when drm_intel_bo_map supports DONTBLOCK
42 if (flags
& PIPE_BUFFER_USAGE_CPU_WRITE
)
45 if (buffer
->map_count
)
49 ret
= drm_intel_gem_bo_map_gtt(bo
);
51 ret
= drm_intel_bo_map(bo
, write
);
53 buffer
->ptr
= bo
->virtual;
64 intel_be_buffer_unmap(struct pipe_winsys
*winsys
,
65 struct pipe_buffer
*buf
)
67 struct intel_be_buffer
*buffer
= intel_be_buffer(buf
);
69 if (--buffer
->map_count
)
73 drm_intel_gem_bo_unmap_gtt(intel_bo(buf
));
75 drm_intel_bo_unmap(intel_bo(buf
));
79 intel_be_buffer_destroy(struct pipe_buffer
*buf
)
81 drm_intel_bo_unreference(intel_bo(buf
));
85 static struct pipe_buffer
*
86 intel_be_buffer_create(struct pipe_winsys
*winsys
,
91 struct intel_be_buffer
*buffer
= CALLOC_STRUCT(intel_be_buffer
);
92 struct intel_be_device
*dev
= intel_be_device(winsys
);
93 drm_intel_bufmgr
*pool
;
99 pipe_reference_init(&buffer
->base
.reference
, 1);
100 buffer
->base
.alignment
= alignment
;
101 buffer
->base
.usage
= usage
;
102 buffer
->base
.size
= size
;
103 buffer
->flinked
= FALSE
;
105 buffer
->map_gtt
= FALSE
;
107 if (usage
& I915_BUFFER_USAGE_SCANOUT
) {
109 name
= "gallium3d_scanout";
110 pool
= dev
->pools
.gem
;
111 } else if (usage
& (PIPE_BUFFER_USAGE_VERTEX
| PIPE_BUFFER_USAGE_CONSTANT
)) {
113 name
= "gallium3d_local";
114 pool
= dev
->pools
.gem
;
115 } else if (usage
& PIPE_BUFFER_USAGE_CUSTOM
) {
116 /* For vertex buffers */
117 name
= "gallium3d_internal_vertex";
118 pool
= dev
->pools
.gem
;
120 /* Regular buffers */
121 name
= "gallium3d_regular";
122 pool
= dev
->pools
.gem
;
125 buffer
->bo
= drm_intel_bo_alloc(pool
, name
, size
, alignment
);
126 if (usage
& I915_BUFFER_USAGE_SCANOUT
) {
127 unsigned tiling
= I915_TILING_X
;
128 unsigned stride
= 2048 * 4; /* TODO do something smarter here */
129 drm_intel_bo_set_tiling(buffer
->bo
, &tiling
, stride
);
130 buffer
->map_gtt
= TRUE
;
136 return &buffer
->base
;
143 static struct pipe_buffer
*
144 intel_be_user_buffer_create(struct pipe_winsys
*winsys
, void *ptr
, unsigned bytes
)
146 struct intel_be_buffer
*buffer
= CALLOC_STRUCT(intel_be_buffer
);
147 struct intel_be_device
*dev
= intel_be_device(winsys
);
153 pipe_reference_init(&buffer
->base
.reference
, 1);
154 buffer
->base
.alignment
= 0;
155 buffer
->base
.usage
= 0;
156 buffer
->base
.size
= bytes
;
158 buffer
->bo
= drm_intel_bo_alloc(dev
->pools
.gem
,
159 "gallium3d_user_buffer",
165 ret
= drm_intel_bo_subdata(buffer
->bo
,
171 return &buffer
->base
;
178 static struct pipe_buffer
*
179 intel_be_surface_buffer_create(struct pipe_winsys
*winsys
,
180 unsigned width
, unsigned height
,
181 enum pipe_format format
,
186 struct pipe_format_block block
;
187 unsigned buf_usage
= 0;
188 unsigned buf_stride
= 0;
189 unsigned buf_size
= 0;
191 pf_get_block(format
, &block
);
192 buf_stride
= pf_get_stride(&block
, width
);
193 buf_stride
= align(buf_stride
, 64);
195 if (tex_usage
& PIPE_TEXTURE_USAGE_PRIMARY
) {
196 /* TODO more checks */
197 assert(buf_stride
<= 2048*4);
198 assert(height
% 8 == 0);
199 buf_stride
= 2048 * 4;
200 buf_usage
|= I915_BUFFER_USAGE_SCANOUT
;
203 buf_size
= buf_stride
* height
;
204 *stride
= buf_stride
;
206 return intel_be_buffer_create(winsys
,
213 intel_be_get_texture_buffer(struct drm_api
*api
,
214 struct pipe_texture
*texture
,
215 struct pipe_buffer
**buffer
,
218 struct intel_be_device
*dev
;
223 dev
= intel_be_device(texture
->screen
->winsys
);
225 return softpipe_get_texture_buffer(texture
, buffer
, stride
);
227 return i915_get_texture_buffer(texture
, buffer
, stride
);
231 intel_be_buffer_from_handle(struct drm_api
*api
,
232 struct pipe_screen
*screen
,
233 const char* name
, unsigned handle
)
235 struct intel_be_device
*dev
= intel_be_device(screen
->winsys
);
236 struct intel_be_buffer
*buffer
= CALLOC_STRUCT(intel_be_buffer
);
241 buffer
->bo
= drm_intel_bo_gem_create_from_name(dev
->pools
.gem
, name
, handle
);
246 pipe_reference_init(&buffer
->base
.reference
, 1);
247 buffer
->base
.screen
= screen
;
248 buffer
->base
.alignment
= buffer
->bo
->align
;
249 buffer
->base
.usage
= PIPE_BUFFER_USAGE_GPU_READ
|
250 PIPE_BUFFER_USAGE_GPU_WRITE
|
251 PIPE_BUFFER_USAGE_CPU_READ
|
252 PIPE_BUFFER_USAGE_CPU_WRITE
;
253 buffer
->base
.size
= buffer
->bo
->size
;
255 return &buffer
->base
;
263 intel_be_handle_from_buffer(struct drm_api
*api
,
264 struct pipe_screen
*screen
,
265 struct pipe_buffer
*buffer
,
271 *handle
= intel_bo(buffer
)->handle
;
276 intel_be_global_handle_from_buffer(struct drm_api
*api
,
277 struct pipe_screen
*screen
,
278 struct pipe_buffer
*buffer
,
281 struct intel_be_buffer
*buf
= intel_be_buffer(buffer
);
287 if (drm_intel_bo_flink(intel_bo(buffer
), &buf
->flink
))
292 *handle
= buf
->flink
;
301 intel_be_fence_refunref(struct pipe_winsys
*sws
,
302 struct pipe_fence_handle
**ptr
,
303 struct pipe_fence_handle
*fence
)
305 struct intel_be_fence
**p
= (struct intel_be_fence
**)ptr
;
306 struct intel_be_fence
*f
= (struct intel_be_fence
*)fence
;
308 intel_be_fence_reference(p
, f
);
312 intel_be_fence_signalled(struct pipe_winsys
*sws
,
313 struct pipe_fence_handle
*fence
,
322 intel_be_fence_finish(struct pipe_winsys
*sws
,
323 struct pipe_fence_handle
*fence
,
326 struct intel_be_fence
*f
= (struct intel_be_fence
*)fence
;
328 /* fence already expired */
332 drm_intel_bo_wait_rendering(f
->bo
);
333 drm_intel_bo_unreference(f
->bo
);
344 intel_be_destroy_winsys(struct pipe_winsys
*winsys
)
346 struct intel_be_device
*dev
= intel_be_device(winsys
);
348 drm_intel_bufmgr_destroy(dev
->pools
.gem
);
354 intel_be_init_device(struct intel_be_device
*dev
, int fd
, unsigned id
)
358 dev
->max_batch_size
= 16 * 4096;
359 dev
->max_vertex_size
= 128 * 4096;
361 dev
->base
.buffer_create
= intel_be_buffer_create
;
362 dev
->base
.user_buffer_create
= intel_be_user_buffer_create
;
363 dev
->base
.buffer_map
= intel_be_buffer_map
;
364 dev
->base
.buffer_unmap
= intel_be_buffer_unmap
;
365 dev
->base
.buffer_destroy
= intel_be_buffer_destroy
;
367 /* Used by softpipe */
368 dev
->base
.surface_buffer_create
= intel_be_surface_buffer_create
;
370 dev
->base
.fence_reference
= intel_be_fence_refunref
;
371 dev
->base
.fence_signalled
= intel_be_fence_signalled
;
372 dev
->base
.fence_finish
= intel_be_fence_finish
;
374 dev
->base
.destroy
= intel_be_destroy_winsys
;
376 dev
->pools
.gem
= drm_intel_bufmgr_gem_init(dev
->fd
, dev
->max_batch_size
);
378 dev
->softpipe
= debug_get_bool_option("INTEL_SOFTPIPE", FALSE
);
379 dev
->dump_cmd
= debug_get_bool_option("INTEL_DUMP_CMD", FALSE
);
385 intel_be_get_device_id(unsigned int *device_id
)
392 * FIXME: Fix this up to use a drm ioctl or whatever.
395 snprintf(path
, sizeof(path
), "/sys/class/drm/card0/device/device");
396 file
= fopen(path
, "r");
401 shutup_gcc
= fgets(path
, sizeof(path
), file
);
402 sscanf(path
, "%x", device_id
);
407 intel_be_create_screen(struct drm_api
*api
, int drmFD
,
408 struct drm_create_screen_arg
*arg
)
410 struct intel_be_device
*dev
;
411 struct pipe_screen
*screen
;
412 unsigned int deviceID
;
416 case DRM_CREATE_NORMAL
:
423 /* Allocate the private area */
424 dev
= malloc(sizeof(*dev
));
427 memset(dev
, 0, sizeof(*dev
));
429 intel_be_get_device_id(&deviceID
);
430 intel_be_init_device(dev
, drmFD
, deviceID
);
433 screen
= softpipe_create_screen(&dev
->base
);
435 screen
= i915_create_screen(&dev
->base
, deviceID
);