1 /**********************************************************
2 * Copyright 2009 VMware, Inc. All rights reserved.
4 * Permission is hereby granted, free of charge, to any person
5 * obtaining a copy of this software and associated documentation
6 * files (the "Software"), to deal in the Software without
7 * restriction, including without limitation the rights to use, copy,
8 * modify, merge, publish, distribute, sublicense, and/or sell copies
9 * of the Software, and to permit persons to whom the Software is
10 * furnished to do so, subject to the following conditions:
12 * The above copyright notice and this permission notice shall be
13 * included in all copies or substantial portions of the Software.
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
17 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
18 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
19 * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
20 * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
21 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
24 **********************************************************/
29 * Wrappers for DRM ioctl functionlaity used by the rest of the vmw
32 * Based on svgaicd_escape.c
37 #include "util/u_memory.h"
38 #include "util/u_math.h"
39 #include "svgadump/svga_dump.h"
40 #include "state_tracker/drm_driver.h"
41 #include "vmw_screen.h"
42 #include "vmw_context.h"
43 #include "vmw_fence.h"
45 #include "vmwgfx_drm.h"
46 #include "svga3d_caps.h"
47 #include "svga3d_reg.h"
49 #include "os/os_mman.h"
54 #define VMW_MAX_DEFAULT_TEXTURE_SIZE (128 * 1024 * 1024)
66 /* XXX: This isn't a real hardware flag, but just a hack for kernel to
67 * know about primary surfaces. In newer versions of the kernel
68 * interface the driver uses a special field.
70 #define SVGA3D_SURFACE_HINT_SCANOUT (1 << 9)
74 vmw_region_size(struct vmw_region
*region
)
80 vmw_ioctl_context_create(struct vmw_winsys_screen
*vws
)
82 struct drm_vmw_context_arg c_arg
;
87 ret
= drmCommandRead(vws
->ioctl
.drm_fd
, DRM_VMW_CREATE_CONTEXT
,
88 &c_arg
, sizeof(c_arg
));
93 vmw_printf("Context id is %d\n", c_arg
.cid
);
99 vmw_ioctl_context_destroy(struct vmw_winsys_screen
*vws
, uint32 cid
)
101 struct drm_vmw_context_arg c_arg
;
105 memset(&c_arg
, 0, sizeof(c_arg
));
108 (void)drmCommandWrite(vws
->ioctl
.drm_fd
, DRM_VMW_UNREF_CONTEXT
,
109 &c_arg
, sizeof(c_arg
));
114 vmw_ioctl_surface_create(struct vmw_winsys_screen
*vws
,
115 SVGA3dSurfaceFlags flags
,
116 SVGA3dSurfaceFormat format
,
119 uint32_t numFaces
, uint32_t numMipLevels
)
121 union drm_vmw_surface_create_arg s_arg
;
122 struct drm_vmw_surface_create_req
*req
= &s_arg
.req
;
123 struct drm_vmw_surface_arg
*rep
= &s_arg
.rep
;
124 struct drm_vmw_size sizes
[DRM_VMW_MAX_SURFACE_FACES
*
125 DRM_VMW_MAX_MIP_LEVELS
];
126 struct drm_vmw_size
*cur_size
;
131 vmw_printf("%s flags %d format %d\n", __FUNCTION__
, flags
, format
);
133 memset(&s_arg
, 0, sizeof(s_arg
));
134 if (vws
->use_old_scanout_flag
&&
135 (flags
& SVGA3D_SURFACE_HINT_SCANOUT
)) {
136 req
->flags
= (uint32_t) flags
;
137 req
->scanout
= false;
138 } else if (flags
& SVGA3D_SURFACE_HINT_SCANOUT
) {
139 req
->flags
= (uint32_t) (flags
& ~SVGA3D_SURFACE_HINT_SCANOUT
);
142 req
->flags
= (uint32_t) flags
;
143 req
->scanout
= false;
145 req
->format
= (uint32_t) format
;
146 req
->shareable
= !!(usage
& SVGA_SURFACE_USAGE_SHARED
);
148 assert(numFaces
* numMipLevels
< DRM_VMW_MAX_SURFACE_FACES
*
149 DRM_VMW_MAX_MIP_LEVELS
);
151 for (iFace
= 0; iFace
< numFaces
; ++iFace
) {
152 SVGA3dSize mipSize
= size
;
154 req
->mip_levels
[iFace
] = numMipLevels
;
155 for (iMipLevel
= 0; iMipLevel
< numMipLevels
; ++iMipLevel
) {
156 cur_size
->width
= mipSize
.width
;
157 cur_size
->height
= mipSize
.height
;
158 cur_size
->depth
= mipSize
.depth
;
159 mipSize
.width
= MAX2(mipSize
.width
>> 1, 1);
160 mipSize
.height
= MAX2(mipSize
.height
>> 1, 1);
161 mipSize
.depth
= MAX2(mipSize
.depth
>> 1, 1);
165 for (iFace
= numFaces
; iFace
< SVGA3D_MAX_SURFACE_FACES
; ++iFace
) {
166 req
->mip_levels
[iFace
] = 0;
169 req
->size_addr
= (unsigned long)&sizes
;
171 ret
= drmCommandWriteRead(vws
->ioctl
.drm_fd
, DRM_VMW_CREATE_SURFACE
,
172 &s_arg
, sizeof(s_arg
));
177 vmw_printf("Surface id is %d\n", rep
->sid
);
184 vmw_ioctl_gb_surface_create(struct vmw_winsys_screen
*vws
,
185 SVGA3dSurfaceFlags flags
,
186 SVGA3dSurfaceFormat format
,
190 uint32_t numMipLevels
,
191 uint32_t buffer_handle
,
192 struct vmw_region
**p_region
)
194 union drm_vmw_gb_surface_create_arg s_arg
;
195 struct drm_vmw_gb_surface_create_req
*req
= &s_arg
.req
;
196 struct drm_vmw_gb_surface_create_rep
*rep
= &s_arg
.rep
;
197 struct vmw_region
*region
= NULL
;
200 vmw_printf("%s flags %d format %d\n", __FUNCTION__
, flags
, format
);
203 region
= CALLOC_STRUCT(vmw_region
);
205 return SVGA3D_INVALID_ID
;
208 memset(&s_arg
, 0, sizeof(s_arg
));
209 if (flags
& SVGA3D_SURFACE_HINT_SCANOUT
) {
210 req
->svga3d_flags
= (uint32_t) (flags
& ~SVGA3D_SURFACE_HINT_SCANOUT
);
211 req
->drm_surface_flags
= drm_vmw_surface_flag_scanout
;
213 req
->svga3d_flags
= (uint32_t) flags
;
215 req
->format
= (uint32_t) format
;
216 if (usage
& SVGA_SURFACE_USAGE_SHARED
)
217 req
->drm_surface_flags
|= drm_vmw_surface_flag_shareable
;
218 req
->drm_surface_flags
|= drm_vmw_surface_flag_create_buffer
;
220 assert(numFaces
* numMipLevels
< DRM_VMW_MAX_SURFACE_FACES
*
221 DRM_VMW_MAX_MIP_LEVELS
);
222 req
->base_size
.width
= size
.width
;
223 req
->base_size
.height
= size
.height
;
224 req
->base_size
.depth
= size
.depth
;
225 req
->mip_levels
= numMipLevels
;
226 req
->multisample_count
= 0;
227 req
->autogen_filter
= SVGA3D_TEX_FILTER_NONE
;
229 req
->buffer_handle
= buffer_handle
;
231 req
->buffer_handle
= SVGA3D_INVALID_ID
;
233 ret
= drmCommandWriteRead(vws
->ioctl
.drm_fd
, DRM_VMW_GB_SURFACE_CREATE
,
234 &s_arg
, sizeof(s_arg
));
237 goto out_fail_create
;
240 region
->handle
= rep
->buffer_handle
;
241 region
->map_handle
= rep
->buffer_map_handle
;
242 region
->drm_fd
= vws
->ioctl
.drm_fd
;
243 region
->size
= rep
->backup_size
;
247 vmw_printf("Surface id is %d\n", rep
->sid
);
252 return SVGA3D_INVALID_ID
;
256 * vmw_ioctl_surface_req - Fill in a struct surface_req
258 * @vws: Winsys screen
259 * @whandle: Surface handle
260 * @req: The struct surface req to fill in
261 * @needs_unref: This call takes a kernel surface reference that needs to
264 * Returns 0 on success, negative error type otherwise.
265 * Fills in the surface_req structure according to handle type and kernel
269 vmw_ioctl_surface_req(const struct vmw_winsys_screen
*vws
,
270 const struct winsys_handle
*whandle
,
271 struct drm_vmw_surface_arg
*req
,
272 boolean
*needs_unref
)
276 switch(whandle
->type
) {
277 case DRM_API_HANDLE_TYPE_SHARED
:
278 case DRM_API_HANDLE_TYPE_KMS
:
279 *needs_unref
= FALSE
;
280 req
->handle_type
= DRM_VMW_HANDLE_LEGACY
;
281 req
->sid
= whandle
->handle
;
283 case DRM_API_HANDLE_TYPE_FD
:
284 if (!vws
->ioctl
.have_drm_2_6
) {
287 ret
= drmPrimeFDToHandle(vws
->ioctl
.drm_fd
, whandle
->handle
, &handle
);
289 vmw_error("Failed to get handle from prime fd %d.\n",
290 (int) whandle
->handle
);
295 req
->handle_type
= DRM_VMW_HANDLE_LEGACY
;
298 *needs_unref
= FALSE
;
299 req
->handle_type
= DRM_VMW_HANDLE_PRIME
;
300 req
->sid
= whandle
->handle
;
304 vmw_error("Attempt to import unsupported handle type %d.\n",
313 * vmw_ioctl_gb_surface_ref - Put a reference on a guest-backed surface and
314 * get surface information
316 * @vws: Screen to register the reference on
317 * @handle: Kernel handle of the guest-backed surface
318 * @flags: flags used when the surface was created
319 * @format: Format used when the surface was created
320 * @numMipLevels: Number of mipmap levels of the surface
321 * @p_region: On successful return points to a newly allocated
322 * struct vmw_region holding a reference to the surface backup buffer.
324 * Returns 0 on success, a system error on failure.
327 vmw_ioctl_gb_surface_ref(struct vmw_winsys_screen
*vws
,
328 const struct winsys_handle
*whandle
,
329 SVGA3dSurfaceFlags
*flags
,
330 SVGA3dSurfaceFormat
*format
,
331 uint32_t *numMipLevels
,
333 struct vmw_region
**p_region
)
335 union drm_vmw_gb_surface_reference_arg s_arg
;
336 struct drm_vmw_surface_arg
*req
= &s_arg
.req
;
337 struct drm_vmw_gb_surface_ref_rep
*rep
= &s_arg
.rep
;
338 struct vmw_region
*region
= NULL
;
339 boolean needs_unref
= FALSE
;
342 vmw_printf("%s flags %d format %d\n", __FUNCTION__
, flags
, format
);
344 assert(p_region
!= NULL
);
345 region
= CALLOC_STRUCT(vmw_region
);
349 memset(&s_arg
, 0, sizeof(s_arg
));
350 ret
= vmw_ioctl_surface_req(vws
, whandle
, req
, &needs_unref
);
355 ret
= drmCommandWriteRead(vws
->ioctl
.drm_fd
, DRM_VMW_GB_SURFACE_REF
,
356 &s_arg
, sizeof(s_arg
));
361 region
->handle
= rep
->crep
.buffer_handle
;
362 region
->map_handle
= rep
->crep
.buffer_map_handle
;
363 region
->drm_fd
= vws
->ioctl
.drm_fd
;
364 region
->size
= rep
->crep
.backup_size
;
367 *handle
= rep
->crep
.handle
;
368 *flags
= rep
->creq
.svga3d_flags
;
369 *format
= rep
->creq
.format
;
370 *numMipLevels
= rep
->creq
.mip_levels
;
373 vmw_ioctl_surface_destroy(vws
, *handle
);
378 vmw_ioctl_surface_destroy(vws
, *handle
);
385 vmw_ioctl_surface_destroy(struct vmw_winsys_screen
*vws
, uint32 sid
)
387 struct drm_vmw_surface_arg s_arg
;
391 memset(&s_arg
, 0, sizeof(s_arg
));
394 (void)drmCommandWrite(vws
->ioctl
.drm_fd
, DRM_VMW_UNREF_SURFACE
,
395 &s_arg
, sizeof(s_arg
));
399 vmw_ioctl_command(struct vmw_winsys_screen
*vws
, int32_t cid
,
400 uint32_t throttle_us
, void *commands
, uint32_t size
,
401 struct pipe_fence_handle
**pfence
)
403 struct drm_vmw_execbuf_arg arg
;
404 struct drm_vmw_fence_rep rep
;
409 static boolean firsttime
= TRUE
;
410 static boolean debug
= FALSE
;
411 static boolean skip
= FALSE
;
413 debug
= debug_get_bool_option("SVGA_DUMP_CMD", FALSE
);
414 skip
= debug_get_bool_option("SVGA_SKIP_CMD", FALSE
);
418 svga_dump_commands(commands
, size
);
427 memset(&arg
, 0, sizeof(arg
));
428 memset(&rep
, 0, sizeof(rep
));
432 arg
.fence_rep
= (unsigned long)&rep
;
433 arg
.commands
= (unsigned long)commands
;
434 arg
.command_size
= size
;
435 arg
.throttle_us
= throttle_us
;
436 arg
.version
= DRM_VMW_EXECBUF_VERSION
;
439 ret
= drmCommandWrite(vws
->ioctl
.drm_fd
, DRM_VMW_EXECBUF
, &arg
, sizeof(arg
));
440 } while(ret
== -ERESTART
);
442 vmw_error("%s error %s.\n", __FUNCTION__
, strerror(-ret
));
448 * Kernel has already synced, or caller requested no fence.
454 vmw_fences_signal(vws
->fence_ops
, rep
.passed_seqno
, rep
.seqno
,
457 *pfence
= vmw_fence_create(vws
->fence_ops
, rep
.handle
,
458 rep
.seqno
, rep
.mask
);
459 if (*pfence
== NULL
) {
461 * Fence creation failed. Need to sync.
463 (void) vmw_ioctl_fence_finish(vws
, rep
.handle
, rep
.mask
);
464 vmw_ioctl_fence_unref(vws
, rep
.handle
);
472 vmw_ioctl_region_create(struct vmw_winsys_screen
*vws
, uint32_t size
)
474 struct vmw_region
*region
;
475 union drm_vmw_alloc_dmabuf_arg arg
;
476 struct drm_vmw_alloc_dmabuf_req
*req
= &arg
.req
;
477 struct drm_vmw_dmabuf_rep
*rep
= &arg
.rep
;
480 vmw_printf("%s: size = %u\n", __FUNCTION__
, size
);
482 region
= CALLOC_STRUCT(vmw_region
);
486 memset(&arg
, 0, sizeof(arg
));
489 ret
= drmCommandWriteRead(vws
->ioctl
.drm_fd
, DRM_VMW_ALLOC_DMABUF
, &arg
,
491 } while (ret
== -ERESTART
);
494 vmw_error("IOCTL failed %d: %s\n", ret
, strerror(-ret
));
499 region
->handle
= rep
->handle
;
500 region
->map_handle
= rep
->map_handle
;
501 region
->map_count
= 0;
503 region
->drm_fd
= vws
->ioctl
.drm_fd
;
505 vmw_printf(" gmrId = %u, offset = %u\n",
506 region
->ptr
.gmrId
, region
->ptr
.offset
);
516 vmw_ioctl_region_destroy(struct vmw_region
*region
)
518 struct drm_vmw_unref_dmabuf_arg arg
;
520 vmw_printf("%s: gmrId = %u, offset = %u\n", __FUNCTION__
,
521 region
->ptr
.gmrId
, region
->ptr
.offset
);
524 os_munmap(region
->data
, region
->size
);
528 memset(&arg
, 0, sizeof(arg
));
529 arg
.handle
= region
->handle
;
530 drmCommandWrite(region
->drm_fd
, DRM_VMW_UNREF_DMABUF
, &arg
, sizeof(arg
));
536 vmw_ioctl_region_ptr(struct vmw_region
*region
)
538 SVGAGuestPtr ptr
= {region
->handle
, 0};
543 vmw_ioctl_region_map(struct vmw_region
*region
)
547 vmw_printf("%s: gmrId = %u, offset = %u\n", __FUNCTION__
,
548 region
->ptr
.gmrId
, region
->ptr
.offset
);
550 if (region
->data
== NULL
) {
551 map
= os_mmap(NULL
, region
->size
, PROT_READ
| PROT_WRITE
, MAP_SHARED
,
552 region
->drm_fd
, region
->map_handle
);
553 if (map
== MAP_FAILED
) {
554 vmw_error("%s: Map failed.\n", __FUNCTION__
);
567 vmw_ioctl_region_unmap(struct vmw_region
*region
)
569 vmw_printf("%s: gmrId = %u, offset = %u\n", __FUNCTION__
,
570 region
->ptr
.gmrId
, region
->ptr
.offset
);
575 * vmw_ioctl_syncforcpu - Synchronize a buffer object for CPU usage
577 * @region: Pointer to a struct vmw_region representing the buffer object.
578 * @dont_block: Dont wait for GPU idle, but rather return -EBUSY if the
579 * GPU is busy with the buffer object.
580 * @readonly: Hint that the CPU access is read-only.
581 * @allow_cs: Allow concurrent command submission while the buffer is
582 * synchronized for CPU. If FALSE command submissions referencing the
583 * buffer will block until a corresponding call to vmw_ioctl_releasefromcpu.
585 * This function idles any GPU activities touching the buffer and blocks
586 * command submission of commands referencing the buffer, even from
590 vmw_ioctl_syncforcpu(struct vmw_region
*region
,
595 struct drm_vmw_synccpu_arg arg
;
597 memset(&arg
, 0, sizeof(arg
));
598 arg
.op
= drm_vmw_synccpu_grab
;
599 arg
.handle
= region
->handle
;
600 arg
.flags
= drm_vmw_synccpu_read
;
602 arg
.flags
|= drm_vmw_synccpu_write
;
604 arg
.flags
|= drm_vmw_synccpu_dontblock
;
606 arg
.flags
|= drm_vmw_synccpu_allow_cs
;
608 return drmCommandWrite(region
->drm_fd
, DRM_VMW_SYNCCPU
, &arg
, sizeof(arg
));
612 * vmw_ioctl_releasefromcpu - Undo a previous syncforcpu.
614 * @region: Pointer to a struct vmw_region representing the buffer object.
615 * @readonly: Should hold the same value as the matching syncforcpu call.
616 * @allow_cs: Should hold the same value as the matching syncforcpu call.
619 vmw_ioctl_releasefromcpu(struct vmw_region
*region
,
623 struct drm_vmw_synccpu_arg arg
;
625 memset(&arg
, 0, sizeof(arg
));
626 arg
.op
= drm_vmw_synccpu_release
;
627 arg
.handle
= region
->handle
;
628 arg
.flags
= drm_vmw_synccpu_read
;
630 arg
.flags
|= drm_vmw_synccpu_write
;
632 arg
.flags
|= drm_vmw_synccpu_allow_cs
;
634 (void) drmCommandWrite(region
->drm_fd
, DRM_VMW_SYNCCPU
, &arg
, sizeof(arg
));
638 vmw_ioctl_fence_unref(struct vmw_winsys_screen
*vws
,
641 struct drm_vmw_fence_arg arg
;
644 memset(&arg
, 0, sizeof(arg
));
647 ret
= drmCommandWrite(vws
->ioctl
.drm_fd
, DRM_VMW_FENCE_UNREF
,
650 vmw_error("%s Failed\n", __FUNCTION__
);
653 static INLINE
uint32_t
654 vmw_drm_fence_flags(uint32_t flags
)
658 if (flags
& SVGA_FENCE_FLAG_EXEC
)
659 dflags
|= DRM_VMW_FENCE_FLAG_EXEC
;
660 if (flags
& SVGA_FENCE_FLAG_QUERY
)
661 dflags
|= DRM_VMW_FENCE_FLAG_QUERY
;
668 vmw_ioctl_fence_signalled(struct vmw_winsys_screen
*vws
,
672 struct drm_vmw_fence_signaled_arg arg
;
673 uint32_t vflags
= vmw_drm_fence_flags(flags
);
676 memset(&arg
, 0, sizeof(arg
));
680 ret
= drmCommandWriteRead(vws
->ioctl
.drm_fd
, DRM_VMW_FENCE_SIGNALED
,
686 vmw_fences_signal(vws
->fence_ops
, arg
.passed_seqno
, 0, FALSE
);
688 return (arg
.signaled
) ? 0 : -1;
694 vmw_ioctl_fence_finish(struct vmw_winsys_screen
*vws
,
698 struct drm_vmw_fence_wait_arg arg
;
699 uint32_t vflags
= vmw_drm_fence_flags(flags
);
702 memset(&arg
, 0, sizeof(arg
));
705 arg
.timeout_us
= 10*1000000;
709 ret
= drmCommandWriteRead(vws
->ioctl
.drm_fd
, DRM_VMW_FENCE_WAIT
,
713 vmw_error("%s Failed\n", __FUNCTION__
);
719 vmw_ioctl_shader_create(struct vmw_winsys_screen
*vws
,
720 SVGA3dShaderType type
,
723 struct drm_vmw_shader_create_arg sh_arg
;
728 memset(&sh_arg
, 0, sizeof(sh_arg
));
730 sh_arg
.size
= code_len
;
731 sh_arg
.buffer_handle
= SVGA3D_INVALID_ID
;
732 sh_arg
.shader_handle
= SVGA3D_INVALID_ID
;
734 case SVGA3D_SHADERTYPE_VS
:
735 sh_arg
.shader_type
= drm_vmw_shader_type_vs
;
737 case SVGA3D_SHADERTYPE_PS
:
738 sh_arg
.shader_type
= drm_vmw_shader_type_ps
;
741 assert(!"Invalid shader type.");
745 ret
= drmCommandWriteRead(vws
->ioctl
.drm_fd
, DRM_VMW_CREATE_SHADER
,
746 &sh_arg
, sizeof(sh_arg
));
749 return SVGA3D_INVALID_ID
;
751 return sh_arg
.shader_handle
;
755 vmw_ioctl_shader_destroy(struct vmw_winsys_screen
*vws
, uint32 shid
)
757 struct drm_vmw_shader_arg sh_arg
;
761 memset(&sh_arg
, 0, sizeof(sh_arg
));
762 sh_arg
.handle
= shid
;
764 (void)drmCommandWrite(vws
->ioctl
.drm_fd
, DRM_VMW_UNREF_SHADER
,
765 &sh_arg
, sizeof(sh_arg
));
770 vmw_ioctl_parse_caps(struct vmw_winsys_screen
*vws
,
771 const uint32_t *cap_buffer
)
775 if (vws
->base
.have_gb_objects
) {
776 for (i
= 0; i
< vws
->ioctl
.num_cap_3d
; ++i
) {
777 vws
->ioctl
.cap_3d
[i
].has_cap
= TRUE
;
778 vws
->ioctl
.cap_3d
[i
].result
.u
= cap_buffer
[i
];
782 const uint32
*capsBlock
;
783 const SVGA3dCapsRecord
*capsRecord
= NULL
;
785 const SVGA3dCapPair
*capArray
;
789 * Search linearly through the caps block records for the specified type.
791 capsBlock
= cap_buffer
;
792 for (offset
= 0; capsBlock
[offset
] != 0; offset
+= capsBlock
[offset
]) {
793 const SVGA3dCapsRecord
*record
;
794 assert(offset
< SVGA_FIFO_3D_CAPS_SIZE
);
795 record
= (const SVGA3dCapsRecord
*) (capsBlock
+ offset
);
796 if ((record
->header
.type
>= SVGA3DCAPS_RECORD_DEVCAPS_MIN
) &&
797 (record
->header
.type
<= SVGA3DCAPS_RECORD_DEVCAPS_MAX
) &&
798 (!capsRecord
|| (record
->header
.type
> capsRecord
->header
.type
))) {
807 * Calculate the number of caps from the size of the record.
809 capArray
= (const SVGA3dCapPair
*) capsRecord
->data
;
810 numCaps
= (int) ((capsRecord
->header
.length
* sizeof(uint32
) -
811 sizeof capsRecord
->header
) / (2 * sizeof(uint32
)));
813 for (i
= 0; i
< numCaps
; i
++) {
814 index
= capArray
[i
][0];
815 if (index
< vws
->ioctl
.num_cap_3d
) {
816 vws
->ioctl
.cap_3d
[index
].has_cap
= TRUE
;
817 vws
->ioctl
.cap_3d
[index
].result
.u
= capArray
[i
][1];
819 debug_printf("Unknown devcaps seen: %d\n", index
);
827 vmw_ioctl_init(struct vmw_winsys_screen
*vws
)
829 struct drm_vmw_getparam_arg gp_arg
;
830 struct drm_vmw_get_3d_cap_arg cap_arg
;
833 uint32_t *cap_buffer
;
834 drmVersionPtr version
;
835 boolean have_drm_2_5
;
839 version
= drmGetVersion(vws
->ioctl
.drm_fd
);
843 have_drm_2_5
= version
->version_major
> 2 ||
844 (version
->version_major
== 2 && version
->version_minor
> 4);
845 vws
->ioctl
.have_drm_2_6
= version
->version_major
> 2 ||
846 (version
->version_major
== 2 && version
->version_minor
> 5);
848 memset(&gp_arg
, 0, sizeof(gp_arg
));
849 gp_arg
.param
= DRM_VMW_PARAM_3D
;
850 ret
= drmCommandWriteRead(vws
->ioctl
.drm_fd
, DRM_VMW_GET_PARAM
,
851 &gp_arg
, sizeof(gp_arg
));
852 if (ret
|| gp_arg
.value
== 0) {
853 vmw_error("No 3D enabled (%i, %s).\n", ret
, strerror(-ret
));
857 memset(&gp_arg
, 0, sizeof(gp_arg
));
858 gp_arg
.param
= DRM_VMW_PARAM_FIFO_HW_VERSION
;
859 ret
= drmCommandWriteRead(vws
->ioctl
.drm_fd
, DRM_VMW_GET_PARAM
,
860 &gp_arg
, sizeof(gp_arg
));
862 vmw_error("Failed to get fifo hw version (%i, %s).\n",
863 ret
, strerror(-ret
));
866 vws
->ioctl
.hwversion
= gp_arg
.value
;
868 memset(&gp_arg
, 0, sizeof(gp_arg
));
869 gp_arg
.param
= DRM_VMW_PARAM_HW_CAPS
;
870 ret
= drmCommandWriteRead(vws
->ioctl
.drm_fd
, DRM_VMW_GET_PARAM
,
871 &gp_arg
, sizeof(gp_arg
));
873 vws
->base
.have_gb_objects
= FALSE
;
875 vws
->base
.have_gb_objects
=
876 !!(gp_arg
.value
& (uint64_t) SVGA_CAP_GBOBJECTS
);
878 if (vws
->base
.have_gb_objects
&& !have_drm_2_5
)
881 if (vws
->base
.have_gb_objects
) {
882 memset(&gp_arg
, 0, sizeof(gp_arg
));
883 gp_arg
.param
= DRM_VMW_PARAM_3D_CAPS_SIZE
;
884 ret
= drmCommandWriteRead(vws
->ioctl
.drm_fd
, DRM_VMW_GET_PARAM
,
885 &gp_arg
, sizeof(gp_arg
));
887 size
= SVGA_FIFO_3D_CAPS_SIZE
* sizeof(uint32_t);
891 if (vws
->base
.have_gb_objects
)
892 vws
->ioctl
.num_cap_3d
= size
/ sizeof(uint32_t);
894 vws
->ioctl
.num_cap_3d
= SVGA3D_DEVCAP_MAX
;
897 memset(&gp_arg
, 0, sizeof(gp_arg
));
898 gp_arg
.param
= DRM_VMW_PARAM_MAX_MOB_MEMORY
;
899 ret
= drmCommandWriteRead(vws
->ioctl
.drm_fd
, DRM_VMW_GET_PARAM
,
900 &gp_arg
, sizeof(gp_arg
));
902 /* Just guess a large enough value. */
903 vws
->ioctl
.max_mob_memory
= 256*1024*1024;
905 vws
->ioctl
.max_mob_memory
= gp_arg
.value
;
908 memset(&gp_arg
, 0, sizeof(gp_arg
));
909 gp_arg
.param
= DRM_VMW_PARAM_MAX_MOB_SIZE
;
910 ret
= drmCommandWriteRead(vws
->ioctl
.drm_fd
, DRM_VMW_GET_PARAM
,
911 &gp_arg
, sizeof(gp_arg
));
913 if (ret
|| gp_arg
.value
== 0) {
914 vws
->ioctl
.max_texture_size
= VMW_MAX_DEFAULT_TEXTURE_SIZE
;
916 vws
->ioctl
.max_texture_size
= gp_arg
.value
;
919 /* Never early flush surfaces, mobs do accounting. */
920 vws
->ioctl
.max_surface_memory
= -1;
922 vws
->ioctl
.num_cap_3d
= SVGA3D_DEVCAP_MAX
;
924 memset(&gp_arg
, 0, sizeof(gp_arg
));
925 gp_arg
.param
= DRM_VMW_PARAM_MAX_SURF_MEMORY
;
927 ret
= drmCommandWriteRead(vws
->ioctl
.drm_fd
, DRM_VMW_GET_PARAM
,
928 &gp_arg
, sizeof(gp_arg
));
929 if (!have_drm_2_5
|| ret
) {
930 /* Just guess a large enough value, around 800mb. */
931 vws
->ioctl
.max_surface_memory
= 0x30000000;
933 vws
->ioctl
.max_surface_memory
= gp_arg
.value
;
936 vws
->ioctl
.max_texture_size
= VMW_MAX_DEFAULT_TEXTURE_SIZE
;
938 size
= SVGA_FIFO_3D_CAPS_SIZE
* sizeof(uint32_t);
941 cap_buffer
= calloc(1, size
);
943 debug_printf("Failed alloc fifo 3D caps buffer.\n");
947 vws
->ioctl
.cap_3d
= calloc(vws
->ioctl
.num_cap_3d
,
948 sizeof(*vws
->ioctl
.cap_3d
));
949 if (!vws
->ioctl
.cap_3d
) {
950 debug_printf("Failed alloc fifo 3D caps buffer.\n");
951 goto out_no_caparray
;
954 memset(&cap_arg
, 0, sizeof(cap_arg
));
955 cap_arg
.buffer
= (uint64_t) (unsigned long) (cap_buffer
);
956 cap_arg
.max_size
= size
;
958 ret
= drmCommandWrite(vws
->ioctl
.drm_fd
, DRM_VMW_GET_3D_CAP
,
959 &cap_arg
, sizeof(cap_arg
));
962 debug_printf("Failed to get 3D capabilities"
963 " (%i, %s).\n", ret
, strerror(-ret
));
967 ret
= vmw_ioctl_parse_caps(vws
, cap_buffer
);
969 debug_printf("Failed to parse 3D capabilities"
970 " (%i, %s).\n", ret
, strerror(-ret
));
974 drmFreeVersion(version
);
975 vmw_printf("%s OK\n", __FUNCTION__
);
978 free(vws
->ioctl
.cap_3d
);
982 drmFreeVersion(version
);
984 vws
->ioctl
.num_cap_3d
= 0;
985 debug_printf("%s Failed\n", __FUNCTION__
);
992 vmw_ioctl_cleanup(struct vmw_winsys_screen
*vws
)