Skip to content
Permalink
Browse files

[rbp] HW mouse pointer

Updating the mouse point provokes a complete screen update which can make it feel laggy
and results in high cpu.

Render the mouse with an overlay to avoid redrawing the normal gui.

Requires recent firmware.
  • Loading branch information...
popcornmix committed Jun 25, 2015
1 parent 2e264b1 commit 5f3d52f4c29cc06c4c5c6bf8aa3a56b514e1cf11
@@ -193,7 +193,9 @@ void CGUIWindowManager::CreateWindows()
Add(new CGUIWindowAddonBrowser);
Add(new CGUIWindowScreensaverDim);
Add(new CGUIWindowDebugInfo);
#ifndef TARGET_RASPBERRY_PI
Add(new CGUIWindowPointer);
#endif
Add(new CGUIDialogYesNo);
Add(new CGUIDialogProgress);
Add(new CGUIDialogExtendedProgressBar);
@@ -28,13 +28,41 @@

#include "cores/omxplayer/OMXImage.h"

#include "guilib/GraphicContext.h"
#include "settings/DisplaySettings.h"

#include <sys/ioctl.h>
#include <linux/ioctl.h>
#include "rpi_user_vcsm.h"

#define MAJOR_NUM 100
#define IOCTL_MBOX_PROPERTY _IOWR(MAJOR_NUM, 0, char *)
#define DEVICE_FILE_NAME "/dev/vcio"

typedef struct gpu_mem_ptr_s {
void *arm; // Pointer to memory mapped on ARM side
int vc_handle; // Videocore handle of relocatable memory
int vcsm_handle; // Handle for use by VCSM
int vc; // Address for use in GPU code
int numbytes; // Size of memory block
int suballoc;
} GPU_MEM_PTR_T;

static int mbox_open();
static void mbox_close(int file_desc);
static void gpu_free_internal(GPU_MEM_PTR_T *p, int mb);
static int gpu_malloc_uncached_internal(int numbytes, GPU_MEM_PTR_T *p, int mb);

CRBP::CRBP()
{
m_initialized = false;
m_omx_initialized = false;
m_DllBcmHost = new DllBcmHost();
m_OMX = new COMXCore();
m_display = DISPMANX_NO_HANDLE;
m_p = NULL;
m_mb = mbox_open();
vcsm_init();
}

CRBP::~CRBP()
@@ -115,7 +143,10 @@ void CRBP::LogFirmwareVerison()
DISPMANX_DISPLAY_HANDLE_T CRBP::OpenDisplay(uint32_t device)
{
if (m_display == DISPMANX_NO_HANDLE)
{
m_display = vc_dispmanx_display_open( 0 /*screen*/ );
init_cursor();
}
return m_display;
}

@@ -124,6 +155,7 @@ void CRBP::CloseDisplay(DISPMANX_DISPLAY_HANDLE_T display)
assert(display == m_display);
vc_dispmanx_display_close(m_display);
m_display = DISPMANX_NO_HANDLE;
uninit_cursor();
}

void CRBP::GetDisplaySize(int &width, int &height)
@@ -224,6 +256,15 @@ void CRBP::Deinitialize()
m_omx_image_init = false;
m_initialized = false;
m_omx_initialized = false;
uninit_cursor();
if (m_mb && m_p)
gpu_free_internal(m_p, m_mb);
delete m_p;
m_p = NULL;
if (m_mb)
mbox_close(m_mb);
m_mb = 0;
vcsm_exit();
}

double CRBP::AdjustHDMIClock(double adjust)
@@ -239,4 +280,217 @@ double CRBP::AdjustHDMIClock(double adjust)
}


static int mbox_property(int file_desc, void *buf)
{
int ret_val = ioctl(file_desc, IOCTL_MBOX_PROPERTY, buf);

if (ret_val < 0) {
printf("ioctl_set_msg failed:%d\n", ret_val);
}
return ret_val;
}

static int mbox_open()
{
int file_desc;

// open a char device file used for communicating with kernel mbox driver
file_desc = open(DEVICE_FILE_NAME, 0);
if (file_desc < 0) {
printf("Can't open device file: %s (%d)\n", DEVICE_FILE_NAME, file_desc);
printf("Try creating a device file with: sudo mknod %s c %d 0\n", DEVICE_FILE_NAME, MAJOR_NUM);
}
return file_desc;
}

static void mbox_close(int file_desc)
{
close(file_desc);
}

static unsigned mem_lock(int file_desc, unsigned handle)
{
int i=0;
unsigned p[32];
p[i++] = 0; // size
p[i++] = 0x00000000; // process request

p[i++] = 0x3000d; // (the tag id)
p[i++] = 4; // (size of the buffer)
p[i++] = 4; // (size of the data)
p[i++] = handle;

p[i++] = 0x00000000; // end tag
p[0] = i*sizeof *p; // actual size

mbox_property(file_desc, p);
return p[5];
}

unsigned mem_unlock(int file_desc, unsigned handle)
{
int i=0;
unsigned p[32];
p[i++] = 0; // size
p[i++] = 0x00000000; // process request

p[i++] = 0x3000e; // (the tag id)
p[i++] = 4; // (size of the buffer)
p[i++] = 4; // (size of the data)
p[i++] = handle;

p[i++] = 0x00000000; // end tag
p[0] = i*sizeof *p; // actual size

mbox_property(file_desc, p);
return p[5];
}

unsigned int mailbox_set_cursor_info(int file_desc, int width, int height, int format, uint32_t buffer, int hotspotx, int hotspoty)
{
int i=0;
unsigned int p[32];
p[i++] = 0; // size
p[i++] = 0x00000000; // process request
p[i++] = 0x00008010; // set cursor state
p[i++] = 24; // buffer size
p[i++] = 24; // data size

p[i++] = width;
p[i++] = height;
p[i++] = format;
p[i++] = buffer; // ptr to VC memory buffer. Doesn't work in 64bit....
p[i++] = hotspotx;
p[i++] = hotspoty;

p[i++] = 0x00000000; // end tag
p[0] = i*sizeof(*p); // actual size

mbox_property(file_desc, p);
return p[5];

}

unsigned int mailbox_set_cursor_position(int file_desc, int enabled, int x, int y)
{
int i=0;
unsigned p[32];
p[i++] = 0; // size
p[i++] = 0x00000000; // process request
p[i++] = 0x00008011; // set cursor state
p[i++] = 12; // buffer size
p[i++] = 12; // data size

p[i++] = enabled;
p[i++] = x;
p[i++] = y;

p[i++] = 0x00000000; // end tag
p[0] = i*sizeof *p; // actual size

mbox_property(file_desc, p);
return p[5];
}

static int gpu_malloc_uncached_internal(int numbytes, GPU_MEM_PTR_T *p, int mb)
{
//printf("%s %d\n", __func__, numbytes);

p->numbytes = numbytes;
p->suballoc = 0;
p->vcsm_handle = vcsm_malloc_cache(numbytes, VCSM_CACHE_TYPE_NONE, (char *)"Mouse pointer");
assert(p->vcsm_handle);
p->vc_handle = vcsm_vc_hdl_from_hdl(p->vcsm_handle);
assert(p->vc_handle);
p->arm = vcsm_lock(p->vcsm_handle);
assert(p->arm);
p->vc = mem_lock(mb, p->vc_handle);
assert(p->vc);
return 0;
}

static void gpu_free_internal(GPU_MEM_PTR_T *p, int mb)
{
mem_unlock(mb,p->vc_handle);
vcsm_unlock_ptr(p->arm);
vcsm_free(p->vcsm_handle);
}

#define T 0
#define W 0xffffffff
#define B 0xff000000

const static uint32_t default_cursor_pixels[] =
{
B,B,B,B,B,B,B,B,B,T,T,T,T,T,T,T,
B,W,W,W,W,W,W,B,T,T,T,T,T,T,T,T,
B,W,W,W,W,W,B,T,T,T,T,T,T,T,T,T,
B,W,W,W,W,B,T,T,T,T,T,T,T,T,T,T,
B,W,W,W,W,W,B,T,T,T,T,T,T,T,T,T,
B,W,W,B,W,W,W,B,T,T,T,T,T,T,T,T,
B,W,B,T,B,W,W,W,B,T,T,T,T,T,T,T,
B,B,T,T,T,B,W,W,W,B,T,T,T,T,T,T,
B,T,T,T,T,T,B,W,W,W,B,T,T,T,T,T,
T,T,T,T,T,T,T,B,W,W,W,B,T,T,T,T,
T,T,T,T,T,T,T,T,B,W,W,W,B,T,T,T,
T,T,T,T,T,T,T,T,T,B,W,W,W,B,T,T,
T,T,T,T,T,T,T,T,T,T,B,W,W,W,B,T,
T,T,T,T,T,T,T,T,T,T,T,B,W,W,W,B,
T,T,T,T,T,T,T,T,T,T,T,T,B,W,B,T,
T,T,T,T,T,T,T,T,T,T,T,T,T,B,T,T
};

#undef T
#undef W
#undef B

void CRBP::init_cursor()
{
//printf("%s\n", __func__);
if (!m_mb)
return;
if (!m_p)
{
m_p = new GPU_MEM_PTR_T;
if (m_p)
gpu_malloc_uncached_internal(64 * 64 * 4, m_p, m_mb);
}
if (m_mb && m_p && m_p->arm && m_p->vc)
set_cursor(default_cursor_pixels, 16, 16, 0, 0);
}

void CRBP::set_cursor(const void *pixels, int width, int height, int hotspot_x, int hotspot_y)
{
if (!m_mb || !m_p || !m_p->arm || !m_p->vc || !pixels || width * height > 64 * 64)
return;
//printf("%s %dx%d %p\n", __func__, width, height, pixels);
memcpy(m_p->arm, pixels, width * height * 4);
unsigned int s = mailbox_set_cursor_info(m_mb, width, height, 0, m_p->vc, hotspot_x, hotspot_y);
assert(s == 0);
}

void CRBP::update_cursor(int x, int y, bool enabled)
{
if (!m_mb || !m_p || !m_p->arm || !m_p->vc)
return;

RESOLUTION res = g_graphicsContext.GetVideoResolution();
CRect gui(0, 0, CDisplaySettings::Get().GetResolutionInfo(res).iWidth, CDisplaySettings::Get().GetResolutionInfo(res).iHeight);
CRect display(0, 0, CDisplaySettings::Get().GetResolutionInfo(res).iScreenWidth, CDisplaySettings::Get().GetResolutionInfo(res).iScreenHeight);

int x2 = x * display.Width() / gui.Width();
int y2 = y * display.Height() / gui.Height();

//printf("%s %d,%d (%d)\n", __func__, x, y, enabled);
mailbox_set_cursor_position(m_mb, enabled, x2, y2);
}

void CRBP::uninit_cursor()
{
if (!m_mb || !m_p || !m_p->arm || !m_p->vc)
return;
//printf("%s\n", __func__);
mailbox_set_cursor_position(m_mb, 0, 0, 0);
}

#endif
@@ -41,6 +41,8 @@
#include "threads/CriticalSection.h"
#include "threads/Event.h"

struct gpu_mem_ptr_s;

class CRBP
{
public:
@@ -81,6 +83,14 @@ class CRBP
CEvent m_vsync;
class DllLibOMXCore;
CCriticalSection m_critSection;

struct gpu_mem_ptr_s *m_p;
int m_mb;
public:
void init_cursor();
void set_cursor(const void *pixels, int width, int height, int hotspot_x, int hotspot_y);
void update_cursor(int x, int y, bool enabled);
void uninit_cursor();
};

extern CRBP g_RBP;

0 comments on commit 5f3d52f

Please sign in to comment.
You can’t perform that action at this time.