/*
* Copyright © 2012 Intel Corporation
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library. If not, see .
*
* Author: Benjamin Segovia
*/
#include "intel_driver.h"
#include "intel_batchbuffer.h"
#include "x11/dricommon.h"
#include
#include
#include
#include
#include
#include
#include
#ifdef __cplusplus
extern "C" {
#endif /* __cplusplus */
#include "cl_utils.h"
#include "cl_alloc.h"
#ifdef __cplusplus
}
#endif /* __cplusplus */
#define SET_BLOCKED_SIGSET(DRIVER) do { \
sigset_t bl_mask; \
sigfillset(&bl_mask); \
sigdelset(&bl_mask, SIGFPE); \
sigdelset(&bl_mask, SIGILL); \
sigdelset(&bl_mask, SIGSEGV); \
sigdelset(&bl_mask, SIGBUS); \
sigdelset(&bl_mask, SIGKILL); \
pthread_sigmask(SIG_SETMASK, &bl_mask, &(DRIVER)->sa_mask); \
} while (0)
#define RESTORE_BLOCKED_SIGSET(DRIVER) do { \
pthread_sigmask(SIG_SETMASK, &(DRIVER)->sa_mask, NULL); \
} while (0)
#define PPTHREAD_MUTEX_LOCK(DRIVER) do { \
SET_BLOCKED_SIGSET(DRIVER); \
pthread_mutex_lock(&(DRIVER)->ctxmutex); \
} while (0)
#define PPTHREAD_MUTEX_UNLOCK(DRIVER) do { \
pthread_mutex_unlock(&(DRIVER)->ctxmutex); \
RESTORE_BLOCKED_SIGSET(DRIVER); \
} while (0)
LOCAL intel_driver_t*
intel_driver_new(void)
{
intel_driver_t *driver = NULL;
TRY_ALLOC_NO_ERR (driver, CALLOC(intel_driver_t));
driver->fd = -1;
exit:
return driver;
error:
intel_driver_delete(driver);
driver = NULL;
goto exit;
}
LOCAL void
intel_driver_delete(intel_driver_t *driver)
{
if (driver == NULL)
return;
cl_free(driver);
}
/* just used for maximum relocation number in drm_intel */
#define BATCH_SIZE 0x1000
static void
intel_driver_memman_init(intel_driver_t *driver)
{
driver->bufmgr = intel_bufmgr_gem_init(driver->fd, BATCH_SIZE);
assert(driver->bufmgr);
intel_bufmgr_gem_enable_reuse(driver->bufmgr);
}
static void
intel_driver_init(intel_driver_t *driver, int dev_fd)
{
driver->fd = dev_fd;
driver->locked = 0;
pthread_mutex_init(&driver->ctxmutex, NULL);
#ifndef NDEBUG
int res =
#endif /* NDEBUG */
intel_driver_get_param(driver, I915_PARAM_CHIPSET_ID, &driver->device_id);
assert(res);
intel_driver_memman_init(driver);
#if EMULATE_GEN
driver->gen_ver = EMULATE_GEN;
if (EMULATE_GEN == 7)
driver->device_id = PCI_CHIP_IVYBRIDGE_GT2; /* we pick GT2 for IVB */
else if (EMULATE_GEN == 6)
driver->device_id = PCI_CHIP_SANDYBRIDGE_GT2; /* we pick GT2 for SNB */
else
FATAL ("Unsupported Gen for emulation");
#else
if (IS_GEN&(driver->device_id))
driver->gen_ver = 7;
else if (IS_GEN6(driver->device_id))
driver->gen_ver = 6;
else if(IS_IGDNG(driver->device_id))
driver->gen_ver = 5;
else
driver->gen_ver = 4;
#endif /* EMULATE_GEN */
}
LOCAL int
intel_driver_get_param(intel_driver_t *driver, int param, int *value)
{
int ret;
struct drm_i915_getparam gp;
gp.param = param;
gp.value = value;
ret = drmCommandWriteRead(driver->fd, DRM_I915_GETPARAM, &gp, sizeof(gp));
return ret == 0;
}
LOCAL int
intel_driver_is_active(intel_driver_t *driver) {
return driver->fd >= 0;
}
LOCAL int
intel_driver_init_shared(intel_driver_t *driver, dri_state_t *state)
{
assert(state);
if(state->driConnectedFlag != DRI2)
return 0;
intel_driver_init(driver, state->fd);
driver->master = 0;
return 1;
}
LOCAL int
intel_driver_init_master(intel_driver_t *driver, const char* dev_name)
{
int dev_fd;
drm_client_t client;
// usually dev_name = "/dev/dri/card%d"
dev_fd = open(dev_name, O_RDWR);
if (dev_fd == -1) return 0;
// Check that we're authenticated and the only opener
client.idx = 0;
int ret = ioctl(dev_fd, DRM_IOCTL_GET_CLIENT, &client);
assert (ret == 0);
if (!client.auth) {
close(dev_fd);
return 0;
}
client.idx = 1;
ret = ioctl(dev_fd, DRM_IOCTL_GET_CLIENT, &client);
if (ret != -1 || errno != EINVAL) {
close(dev_fd);
return 0;
}
intel_driver_init(driver, dev_fd);
driver->master = 1;
return 1;
}
LOCAL int
intel_driver_terminate(intel_driver_t *driver)
{
pthread_mutex_destroy(&driver->ctxmutex);
if(driver->master)
close(driver->fd);
driver->fd = -1;
return 1;
}
LOCAL void
intel_driver_lock_hardware(intel_driver_t *driver)
{
PPTHREAD_MUTEX_LOCK(driver);
assert(!driver->locked);
driver->locked = 1;
}
LOCAL void
intel_driver_unlock_hardware(intel_driver_t *driver)
{
driver->locked = 0;
PPTHREAD_MUTEX_UNLOCK(driver);
}
LOCAL dri_bo*
intel_driver_share_buffer(intel_driver_t *driver, uint32_t name)
{
assert(!driver->master);
dri_bo *bo = intel_bo_gem_create_from_name(driver->bufmgr,
"rendering buffer",
name);
return bo;
}
LOCAL uint32_t
intel_driver_shared_name(intel_driver_t *driver, dri_bo *bo)
{
uint32_t name;
assert(!driver->master);
assert(bo);
dri_bo_flink(bo, &name);
return name;
}
extern drm_intel_bufmgr* intel_driver_get_buf(intel_driver_t*);
LOCAL drm_intel_bufmgr*
intel_driver_get_buf(intel_driver_t *drv)
{
return drv->bufmgr;
}