#include "util/u_debug.h"
#include "util/u_memory.h"
#include "util/u_format.h"
+#include "util/u_hash_table.h"
#include "util/ralloc.h"
+#include <xf86drm.h>
+#include "vc4_drm.h"
#include "vc4_screen.h"
#include "vc4_context.h"
#include "vc4_resource.h"
static const char *
vc4_screen_get_name(struct pipe_screen *pscreen)
{
- return "VC4";
+ struct vc4_screen *screen = vc4_screen(pscreen);
+
+ if (!screen->name) {
+ screen->name = ralloc_asprintf(screen,
+ "VC4 V3D %d.%d",
+ screen->v3d_ver / 10,
+ screen->v3d_ver % 10);
+ }
+
+ return screen->name;
}
static const char *
static void
vc4_screen_destroy(struct pipe_screen *pscreen)
{
+ struct vc4_screen *screen = vc4_screen(pscreen);
+
vc4_bufmgr_destroy(pscreen);
+ close(screen->fd);
ralloc_free(pscreen);
}
case PIPE_CAP_FRAMEBUFFER_NO_ATTACHMENT:
case PIPE_CAP_ROBUST_BUFFER_ACCESS_BEHAVIOR:
case PIPE_CAP_CULL_DISTANCE:
+ case PIPE_CAP_PRIMITIVE_RESTART_FOR_PATCHES:
+ case PIPE_CAP_TGSI_VOTE:
+ case PIPE_CAP_MAX_WINDOW_RECTANGLES:
+ case PIPE_CAP_POLYGON_OFFSET_UNITS_UNSCALED:
+ case PIPE_CAP_VIEWPORT_SUBPIXEL_BITS:
return 0;
/* Stream output. */
case PIPE_SHADER_CAP_MAX_TEX_INSTRUCTIONS:
case PIPE_SHADER_CAP_MAX_TEX_INDIRECTIONS:
return 16384;
+
case PIPE_SHADER_CAP_MAX_CONTROL_FLOW_DEPTH:
- return 0;
+ return vc4_screen(pscreen)->has_control_flow;
+
case PIPE_SHADER_CAP_MAX_INPUTS:
if (shader == PIPE_SHADER_FRAGMENT)
return 8;
return retval == usage;
}
+#define PTR_TO_UINT(x) ((unsigned)((intptr_t)(x)))
+
+static unsigned handle_hash(void *key)
+{
+ return PTR_TO_UINT(key);
+}
+
+static int handle_compare(void *key1, void *key2)
+{
+ return PTR_TO_UINT(key1) != PTR_TO_UINT(key2);
+}
+
+static bool
+vc4_supports_branches(struct vc4_screen *screen)
+{
+#if USE_VC4_SIMULATOR
+ return true;
+#endif
+
+ struct drm_vc4_get_param p = {
+ .param = DRM_VC4_PARAM_SUPPORTS_BRANCHES,
+ };
+ int ret = drmIoctl(screen->fd, DRM_IOCTL_VC4_GET_PARAM, &p);
+
+ if (ret != 0)
+ return false;
+
+ return p.value;
+}
+
+static bool
+vc4_get_chip_info(struct vc4_screen *screen)
+{
+#if USE_VC4_SIMULATOR
+ screen->v3d_ver = 21;
+ return true;
+#endif
+
+ struct drm_vc4_get_param ident0 = {
+ .param = DRM_VC4_PARAM_V3D_IDENT0,
+ };
+ struct drm_vc4_get_param ident1 = {
+ .param = DRM_VC4_PARAM_V3D_IDENT1,
+ };
+ int ret;
+
+ ret = drmIoctl(screen->fd, DRM_IOCTL_VC4_GET_PARAM, &ident0);
+ if (ret != 0) {
+ if (errno == EINVAL) {
+ /* Backwards compatibility with 2835 kernels which
+ * only do V3D 2.1.
+ */
+ screen->v3d_ver = 21;
+ return true;
+ } else {
+ fprintf(stderr, "Couldn't get V3D IDENT0: %s\n",
+ strerror(errno));
+ return false;
+ }
+ }
+ ret = drmIoctl(screen->fd, DRM_IOCTL_VC4_GET_PARAM, &ident1);
+ if (ret != 0) {
+ fprintf(stderr, "Couldn't get V3D IDENT1: %s\n",
+ strerror(errno));
+ return false;
+ }
+
+ uint32_t major = (ident0.value >> 24) & 0xff;
+ uint32_t minor = (ident1.value >> 0) & 0xf;
+ screen->v3d_ver = major * 10 + minor;
+
+ if (screen->v3d_ver != 21) {
+ fprintf(stderr,
+ "V3D %d.%d not supported by this version of Mesa.\n",
+ screen->v3d_ver / 10,
+ screen->v3d_ver % 10);
+ return false;
+ }
+
+ return true;
+}
+
struct pipe_screen *
vc4_screen_create(int fd)
{
screen->fd = fd;
list_inithead(&screen->bo_cache.time_list);
+ pipe_mutex_init(screen->bo_handles_mutex);
+ screen->bo_handles = util_hash_table_create(handle_hash, handle_compare);
+
+ if (vc4_supports_branches(screen))
+ screen->has_control_flow = true;
+
+ if (!vc4_get_chip_info(screen))
+ goto fail;
vc4_fence_init(screen);
pscreen->get_device_vendor = vc4_screen_get_vendor;
return pscreen;
+
+fail:
+ close(fd);
+ ralloc_free(pscreen);
+ return NULL;
}
boolean
{
struct vc4_screen *screen = vc4_screen(pscreen);
+ if (whandle->offset != 0) {
+ fprintf(stderr,
+ "Attempt to import unsupported winsys offset %u\n",
+ whandle->offset);
+ return NULL;
+ }
+
switch (whandle->type) {
case DRM_API_HANDLE_TYPE_SHARED:
return vc4_bo_open_name(screen, whandle->handle, whandle->stride);