Initial commit

This commit is contained in:
2026-04-03 00:22:39 -05:00
commit eca1e8c458
945 changed files with 218160 additions and 0 deletions

View File

@@ -0,0 +1,80 @@
/*
RaspPiPrivate.h
Author: Patrick Baggett <ptbaggett@762studios.com>
Created: 6/25/2013
Purpose:
Private defintions and functions for Raspberry Pi implementation of
libsst-wm
License:
This program is free software. It comes without any warranty, to
the extent permitted by applicable law. You can redistribute it
and/or modify it under the terms of the Do What The Fuck You Want
To Public License, Version 2, as published by Sam Hocevar. See
http://sam.zoy.org/wtfpl/COPYING for more details.
*/
#pragma once
#ifndef _RASPPIPRIVATE_H
#define _RASPPIPRIVATE_H
#include <bcm_host.h>
#include <pthread.h>
#include <SST/SST_WMTypes.h>
#include "EventQueue.h"
/******************************************************************************/
struct SST_Window_RaspPi;
typedef struct SST_DisplayTarget_RaspPi
{
EventQueue eventQueue;
EventQueue userEventQueue;
uint8_t keymapBitvector[32]; /* Bitmap similar to XQueryKeymap() */
pthread_mutex_t eventLock; /* Lock protecting user events */
struct SST_Window_RaspPi* firstWindow; /* Window */
int relativeMouse;
DISPMANX_DISPLAY_HANDLE_T display;
} SST_DisplayTarget_RaspPi;
/******************************************************************************/
typedef struct SST_Window_RaspPi
{
SST_DisplayTarget_RaspPi* owner;
struct SST_Window_RaspPi* next;
int isFullscreen;
uint32_t x, y;
uint32_t w, h;
DISPMANX_ELEMENT_HANDLE_T element;
/* Software rendering support */
void* softwareBackbuffer;
uint32_t softwarePitch;
DISPMANX_RESOURCE_HANDLE_T softwareImage;
VC_RECT_T softwareRect;
} SST_Window_RaspPi;
/******************************************************************************/
typedef struct SST_OpenGLContext_RaspPi
{
SST_DisplayTarget_RaspPi* displayTarget;
uint16_t ctxVersion[2]; /* context version major/minor */
int debugEnabled; /* Did we use debug OpenGL context support? */
/* EGL fields */
/* TODO */
} SST_OpenGLContext_RaspPi;
/******************************************************************************/
#endif

View File

@@ -0,0 +1,49 @@
/*
SST_WMDialogBox_RaspPi.c
Author: Patrick Baggett <ptbaggett@762studios.com>
Created: 6/25/2013
Purpose:
Simple dialog box window
License:
This program is free software. It comes without any warranty, to
the extent permitted by applicable law. You can redistribute it
and/or modify it under the terms of the Do What The Fuck You Want
To Public License, Version 2, as published by Sam Hocevar. See
http://sam.zoy.org/wtfpl/COPYING for more details.
*/
#include "RaspPiPrivate.h"
#define BUTTON_HSPACE 16 /* Space on either side of a button */
#define BUTTON_VSPACE 16 /* Space between top of button and dialog text */
#define TEXT_HSPACE 16
#define TEXT_VSPACE 16
typedef struct DialogBoxData
{
const char* message;
int lenMessage;
int buttonId;
int exitTime;
} DialogBoxData;
/******************************************************************************/
int SST_WM_ShowDialogBox(SST_DisplayTarget target, SST_Window parent, const char* caption, const char* message, const char** buttons, int nrButtons)
{
/* TODO: helluvalota work */
(void)target;
(void)parent;
(void)caption;
(void)message;
(void)buttons;
(void)nrButtons;
return 0;
}

View File

@@ -0,0 +1,144 @@
/*
SST_WMEnum_RaspPi.c
Author: Patrick Baggett <ptbaggett@762studios.com>
Created: 5/31/2013
Purpose:
Raspberry Pi native (no display server) port for Linux
License:
This program is free software. It comes without any warranty, to
the extent permitted by applicable law. You can redistribute it
and/or modify it under the terms of the Do What The Fuck You Want
To Public License, Version 2, as published by Sam Hocevar. See
http://sam.zoy.org/wtfpl/COPYING for more details.
*/
#include <SST/SST_WM.h>
#include <bcm_host.h> /* R-Pi header */
#include <string.h> /* strlen() etc. */
#include <stdlib.h>
/******************************************************************************/
SST_GraphicsEnumerator SST_WM_CreateGraphicsEnumerator(void)
{
/* Call this just in case. Multiple calls do not affect anything */
bcm_host_init();
return (void*)(uintptr_t)(0x40000000); /* No, it is meaningless */
}
/******************************************************************************/
size_t SST_WM_GetEnumAdapterCount(SST_GraphicsEnumerator enumerator)
{
(void)enumerator;
/* R-Pi only has the one on-chip device */
return 1;
}
/******************************************************************************/
void SST_WM_GetEnumAdapterName(SST_GraphicsEnumerator enumerator, size_t adapterId, char* nameReturn, size_t* bufferSize)
{
size_t len;
const char* name = "VideoCore IV (R) GPU";
(void)enumerator;
(void)adapterId;
len = strlen(name);
/* Query name length */
if(nameReturn == NULL)
{
*bufferSize = len+1;
}
else
{
size_t copyAmount;
/* Nothing to do? */
if(*bufferSize == 0)
return;
/* Use min(len, (*bufferSize)-1) */
copyAmount = len;
if(copyAmount > (*bufferSize)-1)
copyAmount = (*bufferSize)-1;
memcpy(nameReturn, name, copyAmount);
nameReturn[copyAmount] = '\0';
}
}
/******************************************************************************/
size_t SST_WM_GetEnumScreenCount(SST_GraphicsEnumerator enumerator, size_t adapterId)
{
(void)enumerator;
(void)adapterId;
return 1;
}
/******************************************************************************/
void SST_WM_GetEnumVideoModes(SST_GraphicsEnumerator enumerator, size_t adapterId, size_t screenId, SST_VideoMode* modesReturn, size_t* modeCountReturn)
{
(void)enumerator;
/* Only one adapter/screen supported */
if(adapterId != 0 || screenId != 0)
return;
if(modesReturn == NULL)
*modeCountReturn = 1;
else
{
/* TODO: there might be a way to do this, but it
is very manual. Just return current resolution. */
uint32_t w, h;
graphics_get_display_size(0, &w, &h);
modesReturn[0].bpp = 16; /* TODO: not always 16 */
modesReturn[0].width = w;
modesReturn[0].height = h;
modesReturn[0].refreshRate = 0;
}
}
/******************************************************************************/
void SST_WM_GetEnumCurrentVideoMode(SST_GraphicsEnumerator enumerator, size_t adapterId, size_t screenId, SST_VideoMode* mode)
{
uint32_t w, h;
(void)enumerator;
if(adapterId != 0 || screenId != 0)
return;
/* TODO: does this reflect changes made with fbset? */
graphics_get_display_size(0, &w, &h);
mode->bpp = 16;
mode->width = w;
mode->height = h;
mode->refreshRate = 0;
}
/******************************************************************************/
void SST_WM_DestroyGraphicsEnumerator(SST_GraphicsEnumerator enumerator)
{
(void)enumerator;
}

View File

@@ -0,0 +1,60 @@
/*
SST_WMEvent_Win32.c
Author: Patrick Baggett <ptbaggett@762studios.com>
Created: 6/25/2013
Purpose:
Raspberry Pi "window" event functions
License:
This program is free software. It comes without any warranty, to
the extent permitted by applicable law. You can redistribute it
and/or modify it under the terms of the Do What The Fuck You Want
To Public License, Version 2, as published by Sam Hocevar. See
http://sam.zoy.org/wtfpl/COPYING for more details.
*/
#include <SST/SST_WMEvent.h>
#include "RaspPiPrivate.h"
/******************************************************************************/
int SST_WM_GetEvent(SST_DisplayTarget target, SST_WMEvent* eventReturn)
{
SST_DisplayTarget_RaspPi* displayTarget = (SST_DisplayTarget_RaspPi*)target;
/* Check for user events */
if(RemoveFromEQ(&displayTarget->userEventQueue, eventReturn))
return 1;
if(RemoveFromEQ(&displayTarget->eventQueue, eventReturn))
return 1;
return 0;
}
/******************************************************************************/
/* These functions are used by SST_WMEvent_Common.c */
EventQueue* getUserEventQueue(SST_DisplayTarget target)
{
SST_DisplayTarget_RaspPi* displayTarget = (SST_DisplayTarget_RaspPi*)target;
return &displayTarget->userEventQueue;
}
void lockUserEventQueue(SST_DisplayTarget target)
{
SST_DisplayTarget_RaspPi* displayTarget = (SST_DisplayTarget_RaspPi*)target;
pthread_mutex_lock(&displayTarget->eventLock);
}
void unlockUserEventQueue(SST_DisplayTarget target)
{
SST_DisplayTarget_RaspPi* displayTarget = (SST_DisplayTarget_RaspPi*)target;
pthread_mutex_unlock(&displayTarget->eventLock);
}

View File

@@ -0,0 +1,113 @@
/*
SST_WMRender_RaspPi.c
Author: Patrick Baggett <ptbaggett@762studios.com>
Created: 6/25/2013
Purpose:
Software rendering support for Raspberry Pi
License:
This program is free software. It comes without any warranty, to
the extent permitted by applicable law. You can redistribute it
and/or modify it under the terms of the Do What The Fuck You Want
To Public License, Version 2, as published by Sam Hocevar. See
http://sam.zoy.org/wtfpl/COPYING for more details.
*/
#include "RaspPiPrivate.h"
#include <SST/SST_WMWindow.h>
#define ROUNDUP(val, power) ((val + (power)-1) & ~((power)-1))
/******************************************************************************/
int SST_WM_EnableSoftwareRendering(SST_Window window)
{
SST_Window_RaspPi* win = (SST_Window_RaspPi*)window;
DISPMANX_UPDATE_HANDLE_T update;
/* Each pixel is 4 bytes. */
uint32_t pitch = win->w * sizeof(uint32_t);
uint32_t dummy;
/* Pitch must be a multiple of 32 bytes, so round up */
pitch = ROUNDUP(pitch, 32);
/* TODO: what does vc_dispmanx_resource_create() return on error? */
/* Last parameter "dummy" is always set to zero according to source code, must be from other videocore versions */
win->softwareImage = vc_dispmanx_resource_create(VC_IMAGE_ARGB8888, win->w, win->h, &dummy);
win->softwareBackbuffer = calloc(win->h, pitch);
win->softwarePitch = pitch;
/* TODO: wtf, why << 16 */
vc_dispmanx_rect_set(&win->softwareRect, 0, 0, win->w << 16, win->h << 16 );
if(win->softwareBackbuffer == NULL)
return 0;
/* Update dispmanx to bind the new image to the */
update = vc_dispmanx_update_start(0);
vc_dispmanx_element_change_source(update, win->element, win->softwareImage);
vc_dispmanx_update_submit_sync(update);
return 1;
}
/******************************************************************************/
void SST_WM_DisableSoftwareRendering(SST_Window window)
{
SST_Window_RaspPi* win = (SST_Window_RaspPi*)window;
DISPMANX_UPDATE_HANDLE_T update;
/* Update dispmanx; remove the resource from the window element */
update = vc_dispmanx_update_start(0);
vc_dispmanx_element_change_source(update, win->element, 0);
vc_dispmanx_update_submit_sync(update);
/* Now we can delete the resource */
if(win->softwareImage != 0)
{
vc_dispmanx_resource_delete(win->softwareImage);
win->softwareImage = 0;
}
if(win->softwareBackbuffer)
{
free(win->softwareBackbuffer);
win->softwareBackbuffer = NULL;
}
}
/******************************************************************************/
void* SST_WM_LockBackbuffer(SST_Window window, size_t* pitchReturn)
{
SST_Window_RaspPi* win = (SST_Window_RaspPi*)window;
*pitchReturn = win->softwarePitch;
return win->softwareBackbuffer;
}
/******************************************************************************/
void SST_WM_UnlockBackbuffer(SST_Window window)
{
SST_Window_RaspPi* win = (SST_Window_RaspPi*)window;
VC_RECT_T blit;
blit.x = blit.y = 0;
blit.width = win->w;
blit.height = win->h;
/* Push the pixels to the resource */
vc_dispmanx_resource_write_data(win->softwareImage, VC_IMAGE_ARGB8888, win->softwarePitch, win->softwareBackbuffer, &blit);
}

View File

@@ -0,0 +1,56 @@
/*
SST_WMVideoMode_RaspPi.c
Author: Patrick Baggett <ptbaggett@762studios.com>
Created: 6/25/2013
Purpose:
Video mode setting functions for the Raspberry Pi
License:
This program is free software. It comes without any warranty, to
the extent permitted by applicable law. You can redistribute it
and/or modify it under the terms of the Do What The Fuck You Want
To Public License, Version 2, as published by Sam Hocevar. See
http://sam.zoy.org/wtfpl/COPYING for more details.
*/
#include "RaspPiPrivate.h"
/*
Right now, these are essentially no-ops. The vc_tv_xxx API can be used
to query and change the video mode
*/
/******************************************************************************/
int SST_WM_SetVideoModeOnScreen(SST_DisplayTarget target, size_t screenIndex, const SST_VideoMode* vmode)
{
SST_DisplayTarget_RaspPi* displayTarget = (SST_DisplayTarget_RaspPi*)target;
/* Must be screen 0 */
if(screenIndex != 0)
return 0;
return 1;
}
/******************************************************************************/
int SST_WM_GetVideoModeOnScreen(SST_DisplayTarget target, size_t screenIndex, SST_VideoMode* vmodeReturn)
{
SST_DisplayTarget_RaspPi* displayTarget = (SST_DisplayTarget_RaspPi*)target;
/* Must be screen 0 */
if(screenIndex != 0)
return 0;
vmodeReturn->bpp = 16; /* ? The HWS runs at what depth? */
vmodeReturn->width = 0;
vmodeReturn->height = 0;
vmodeReturn->refreshRate = 0;
return 1;
}

View File

@@ -0,0 +1,390 @@
/*
SST_WMWindow_RaspPi.c
Author: Patrick Baggett <ptbaggett@762studios.com>
Created: 1/8/2013
Purpose:
Window emulation for native Raspberry Pi port
License:
This program is free software. It comes without any warranty, to
the extent permitted by applicable law. You can redistribute it
and/or modify it under the terms of the Do What The Fuck You Want
To Public License, Version 2, as published by Sam Hocevar. See
http://sam.zoy.org/wtfpl/COPYING for more details.
*/
#include <SST/SST_WMWindow.h>
#include "RaspPiPrivate.h"
#include "EventQueue.h"
#define WINDOW_LAYER 2000
/******************************************************************************/
static void destroyWin(SST_Window_RaspPi* win)
{
/* Only after an element is removed can the resource under it
be deleted. */
if(win->element != 0)
{
DISPMANX_UPDATE_HANDLE_T update;
update = vc_dispmanx_update_start(0);
vc_dispmanx_element_remove(update, win->element);
vc_dispmanx_update_submit_sync(update);
}
if(win->softwareImage != 0)
vc_dispmanx_resource_delete(win->softwareImage);
free(win);
}
/******************************************************************************/
SST_DisplayTarget SST_WM_CreateDisplayTarget(size_t adapterIndex, size_t screenIndexOrMultihead)
{
SST_DisplayTarget_RaspPi* displayTarget;
/* > 1 adapters not supported, multihead not supported */
if(screenIndexOrMultihead != 0 || adapterIndex != 0)
return NULL;
displayTarget = (SST_DisplayTarget_RaspPi*)malloc(sizeof(SST_DisplayTarget_RaspPi));
if(displayTarget == NULL)
return NULL;
/* Initialize lock for user events */
if(pthread_mutex_init(&displayTarget->eventLock, NULL) != 0)
{
free(displayTarget);
return NULL;
}
if(InitEQ(&displayTarget->eventQueue) == 0)
{
pthread_mutex_destroy(&displayTarget->eventLock);
free(displayTarget);
return NULL;
}
if(InitEQ(&displayTarget->userEventQueue) == 0)
{
DestroyEQ(&displayTarget->eventQueue);
pthread_mutex_destroy(&displayTarget->eventLock);
free(displayTarget);
return NULL;
}
/* Save fields */
displayTarget->firstWindow = NULL;
displayTarget->relativeMouse = 0;
displayTarget->display = vc_dispmanx_display_open(DISPMANX_ID_MAIN_LCD);
memset(displayTarget->keymapBitvector, 0, sizeof(displayTarget->keymapBitvector));
return (SST_DisplayTarget)displayTarget;
}
/******************************************************************************/
size_t SST_WM_GetDisplayTargetScreenCount(SST_DisplayTarget target)
{
(void)target;
return 1;
}
/******************************************************************************/
SST_Window SST_WM_CreateWindowOnScreen(SST_DisplayTarget target, size_t screenIndex, uint32_t x, uint32_t y, uint32_t width, uint32_t height, const char* title)
{
SST_Window_RaspPi* win;
SST_DisplayTarget_RaspPi* displayTarget = (SST_DisplayTarget_RaspPi*)target;
SST_WMEvent* event;
DISPMANX_UPDATE_HANDLE_T update;
VC_DISPMANX_ALPHA_T alpha;
VC_RECT_T srcRect, dstRect;
/* Title is not used */
(void)title;
/* Must be on screen 0 */
if(screenIndex != 0)
return NULL;
/* Allocate SST window structure */
win = (SST_Window_RaspPi*)calloc(1, sizeof(SST_Window_RaspPi));
if(win == NULL)
return NULL;
/* link the window */
displayTarget->firstWindow = win;
win->next = displayTarget->firstWindow;
win->owner = displayTarget;
win->x = x;
win->y = y;
win->w = width;
win->h = height;
srcRect.x = srcRect.y = 0;
srcRect.width = width << 16; srcRect.height = height << 16;
dstRect.x = x; dstRect.y = y;
dstRect.width = width; dstRect.height = height;
/* TODO: clip these so they make sense */
alpha.flags = DISPMANX_FLAGS_ALPHA_FIXED_ALL_PIXELS;
alpha.opacity = 0xFF;
alpha.mask = 0;
update = vc_dispmanx_update_start(0);
win->element = vc_dispmanx_element_add(update, displayTarget->display,
WINDOW_LAYER,
&dstRect,
0, &srcRect, /* no source data */
DISPMANX_PROTECTION_NONE, /* no content protection */
&alpha, NULL, /* Alpha/clamp/transform parameters */
VC_IMAGE_ROT0); /* No rotation required */
vc_dispmanx_update_submit_sync(update);
/* Add a SSTWMEVENT_CREATED event */
event = AllocSlotInEQ(&displayTarget->eventQueue);
if(event != NULL)
{
event->window = win;
event->type = SSTWMEVENT_CREATED;
memset(&event->details, 0, sizeof(event->details));
}
return (SST_Window)win;
}
/******************************************************************************/
SST_DisplayTarget SST_WM_GetWindowDisplayTarget(SST_Window window)
{
SST_Window_RaspPi* win = (SST_Window_RaspPi*)window;
return win->owner;
}
/******************************************************************************/
void SST_WM_SetWindowText(SST_Window window, const char* titleBar)
{
/* There is no way to do this; Ignore. */
(void)window;
(void)titleBar;
}
/******************************************************************************/
void SST_WM_GetWindowRect(SST_Window window, SST_Rect* rectReturn)
{
SST_Window_RaspPi* win = (SST_Window_RaspPi*)window;
rectReturn->x = win->x;
rectReturn->y = win->y;
rectReturn->width = win->w;
rectReturn->height = win->h;
return;
}
/******************************************************************************/
void SST_WM_MoveWindowOnScreen(SST_Window window, size_t screenIndex, uint32_t x, uint32_t y)
{
SST_Window_RaspPi* win = (SST_Window_RaspPi*)window;
/* Only allow operations on screen 0 */
if(screenIndex != SST_SAME_SCREEN && screenIndex != 0)
return;
/* TODO: verify these coords make any sense */
win->x = x;
win->y = y;
/* TODO: send message */
}
/******************************************************************************/
void SST_WM_ResizeWindow(SST_Window window, uint32_t width, uint32_t height)
{
SST_Window_RaspPi* win = (SST_Window_RaspPi*)window;
/* TODO: verify these coords make any sense */
win->w = width;
win->h = height;
/* TODO: send a message */
}
/******************************************************************************/
void SST_WM_SetWindowState(SST_Window window, SST_WMWindowState state, uint32_t param)
{
SST_Window_RaspPi* win = (SST_Window_RaspPi*)window;
switch(state)
{
case SSTWS_SHOWN:
{
/* Map or unmap the window respectively */
if(param == 0)
{
/* TODO: hide window */
}
else
{
/* TODO: show window */
}
break;
}
/* Turn on/off resizeability */
case SSTWS_RESIZEABLE:
{
/* No-op. */
break;
}
case SSTWS_FULLSCREEN:
{
/* Enabling fullscreen? */
if(param && !win->isFullscreen)
{
/* TODO: save old X/Y/W/H */
win->isFullscreen = 1;
}
else if(win->isFullscreen)
{
/* TODO: restore old X/Y/W/H */
win->isFullscreen = 0;
}
break;
}
case SSTWS_MINIMIZED:
{
if(param == 0) /* Maximize */
{
/* TODO: maximize? */
}
else /* Minimize */
{
/* TODO: minimize? */
}
break;
}
default: break;
}
}
/******************************************************************************/
void SST_WM_SetDisplayTargetState(SST_DisplayTarget target, SST_WMDisplayTargetState state, uint32_t param)
{
SST_DisplayTarget_RaspPi* displayTarget = (SST_DisplayTarget_RaspPi*)target;
switch(state)
{
case SSTDTS_RELMOUSE:
{
/* Disabling? */
if(displayTarget->relativeMouse && param == 0)
{
/* TODO */
}
else if(!displayTarget->relativeMouse && param != 0) /* Enabling? */
{
/* TODO */
}
break;
}
}
}
/******************************************************************************/
void SST_WM_DestroyWindow(SST_Window window)
{
SST_DisplayTarget_RaspPi* displayTarget;
SST_Window_RaspPi* win = (SST_Window_RaspPi*)window;
SST_Window_RaspPi* nextWin;
displayTarget = win->owner;
nextWin = displayTarget->firstWindow;
/* Special case: root window */
if(nextWin == win)
{
/* Set new root to be this->next */
displayTarget->firstWindow = win->next;
}
else
{
int found = 0;
/* Check list */
while(nextWin)
{
/* Did we find the window? */
if(nextWin->next == win)
{
/* Remove this window from the linked list */
nextWin->next = win->next;
found = 1;
break;
}
else
nextWin = nextWin->next;
}
/* Don't destroy another display target's window */
if(!found)
return;
}
/* Actually destroy the window window */
destroyWin(win);
}
/******************************************************************************/
void SST_WM_DestroyDisplayTarget(SST_DisplayTarget target)
{
SST_DisplayTarget_RaspPi* displayTarget = (SST_DisplayTarget_RaspPi*)target;
SST_Window_RaspPi* window = displayTarget->firstWindow;
/* Destroy window */
while(window)
{
SST_Window_RaspPi* next = window->next;
destroyWin(window);
window = next;
}
/* Delete any events */
DestroyEQ(&displayTarget->eventQueue);
DestroyEQ(&displayTarget->userEventQueue);
pthread_mutex_destroy(&displayTarget->eventLock);
vc_dispmanx_display_close(displayTarget->display);
/* Free structure */
free(displayTarget);
}
/******************************************************************************/