mirror of
https://github.com/glfw/glfw.git
synced 2025-07-12 18:50:04 +00:00
565 lines
15 KiB
C
565 lines
15 KiB
C
//========================================================================
|
|
// GLFW 3.5 OGC - www.glfw.org
|
|
//------------------------------------------------------------------------
|
|
// Copyright (c) 2024 Alberto Mardegan <info@mardy.it>
|
|
//
|
|
// This software is provided 'as-is', without any express or implied
|
|
// warranty. In no event will the authors be held liable for any damages
|
|
// arising from the use of this software.
|
|
//
|
|
// Permission is granted to anyone to use this software for any purpose,
|
|
// including commercial applications, and to alter it and redistribute it
|
|
// freely, subject to the following restrictions:
|
|
//
|
|
// 1. The origin of this software must not be misrepresented; you must not
|
|
// claim that you wrote the original software. If you use this software
|
|
// in a product, an acknowledgment in the product documentation would
|
|
// be appreciated but is not required.
|
|
//
|
|
// 2. Altered source versions must be plainly marked as such, and must not
|
|
// be misrepresented as being the original software.
|
|
//
|
|
// 3. This notice may not be removed or altered from any source
|
|
// distribution.
|
|
//
|
|
//========================================================================
|
|
|
|
#define _GNU_SOURCE
|
|
|
|
#include "internal.h"
|
|
|
|
#if defined(_GLFW_OGC)
|
|
|
|
#include "ogc_cursor.h"
|
|
|
|
#include <assert.h>
|
|
#include <errno.h>
|
|
#include <malloc.h>
|
|
#include <opengx.h>
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
#include <wiikeyboard/keyboard.h>
|
|
#ifdef __wii__
|
|
#include <wiiuse/wpad.h>
|
|
#endif
|
|
|
|
static void keysym_to_utf8(uint16_t symbol, char *utf8)
|
|
{
|
|
/* ignore private symbols, used by wiikeyboard for special keys */
|
|
if ((symbol >= 0xE000 && symbol <= 0xF8FF) || symbol == 0xFFFF)
|
|
return;
|
|
|
|
/* convert UCS-2 to UTF-8 */
|
|
if (symbol < 0x80) {
|
|
utf8[0] = symbol;
|
|
} else if (symbol < 0x800) {
|
|
utf8[0] = 0xC0 | (symbol >> 6);
|
|
utf8[1] = 0x80 | (symbol & 0x3F);
|
|
} else {
|
|
utf8[0] = 0xE0 | (symbol >> 12);
|
|
utf8[1] = 0x80 | ((symbol >> 6) & 0x3F);
|
|
utf8[2] = 0x80 | (symbol & 0x3F);
|
|
}
|
|
}
|
|
|
|
static void acquireMonitor(_GLFWwindow* window)
|
|
{
|
|
fprintf(stderr, "%s:%d %s\n", __FILE__, __LINE__, __func__);
|
|
if (!window->monitor) {
|
|
window->monitor = _glfw.monitors[0];
|
|
}
|
|
_glfwInputMonitorWindow(window->monitor, window);
|
|
_glfwSetVideoModeOgc(window->monitor, &window->videoMode);
|
|
}
|
|
|
|
static void releaseMonitor(_GLFWwindow* window)
|
|
{
|
|
if (window->monitor->window != window)
|
|
return;
|
|
|
|
_glfwInputMonitorWindow(window->monitor, NULL);
|
|
}
|
|
|
|
/* Convert the RGBA pixels to the 4x4 tile ARGB texture used by GX */
|
|
static void setPixelToTextureARGB(char *texture, u32 offset, u32 color)
|
|
{
|
|
*(u16*)(texture + offset) = color >> 16;
|
|
*(u16*)(texture + offset + 32) = color;
|
|
}
|
|
|
|
static void setPixelToTextureRGBA(char *texture, u32 offset, u32 color)
|
|
{
|
|
setPixelToTextureARGB(texture, offset, (color << 24) | (color >> 8));
|
|
}
|
|
|
|
static void pixelsToTextureARGB(const void *pixels, s16 width, s16 height,
|
|
s16 pitch, void *texture)
|
|
{
|
|
s16 tex_pitch = (width + 3) / 4 * 4;
|
|
int row, col;
|
|
|
|
for (row = 0; row < height; row++) {
|
|
int y = row;
|
|
u32 *src = (u32 *)((u8 *)pixels + pitch * row);
|
|
for (col = 0; col < width; col++) {
|
|
int x = col;
|
|
u32 offset = (((y >> 2) << 4) * tex_pitch) +
|
|
((x >> 2) << 6) + (((y % 4 << 2) + x % 4) << 1);
|
|
setPixelToTextureRGBA(texture, offset, *src++);
|
|
}
|
|
}
|
|
}
|
|
|
|
static void* createRGBAtexture(const GLFWimage* image)
|
|
{
|
|
u32 textureSize;
|
|
void *texels;
|
|
|
|
textureSize = GX_GetTexBufferSize(image->width, image->height, GX_TF_RGBA8,
|
|
GX_FALSE, 0);
|
|
texels = memalign(32, textureSize);
|
|
if (!texels) {
|
|
_glfwInputError(GLFW_OUT_OF_MEMORY,
|
|
"OGC: Failed to allocate cursor texture");
|
|
return NULL;
|
|
}
|
|
|
|
pixelsToTextureARGB(image->pixels, image->width, image->height,
|
|
image->width * 4, texels);
|
|
DCStoreRange(texels, textureSize);
|
|
return texels;
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
////// GLFW platform API //////
|
|
//////////////////////////////////////////////////////////////////////////
|
|
|
|
GLFWbool _glfwCreateWindowOgc(_GLFWwindow* window,
|
|
const _GLFWwndconfig* wndconfig,
|
|
const _GLFWctxconfig* ctxconfig,
|
|
const _GLFWfbconfig* fbconfig)
|
|
{
|
|
fprintf(stderr, "%s:%d %s %p\n", __FILE__, __LINE__, __func__, window);
|
|
|
|
acquireMonitor(window);
|
|
window->ogc.width = window->monitor->ogc.ogcMode->fbWidth;
|
|
window->ogc.height = window->monitor->ogc.ogcMode->efbHeight;
|
|
|
|
if (ctxconfig->client != GLFW_NO_API)
|
|
{
|
|
ogx_initialize();
|
|
|
|
if (!_glfwCreateContextOgc(window, ctxconfig, fbconfig))
|
|
return GLFW_FALSE;
|
|
|
|
if (!_glfwRefreshContextAttribs(window, ctxconfig))
|
|
return GLFW_FALSE;
|
|
}
|
|
|
|
/* Set the default Wii cursor */
|
|
GLFWcursor *cursor = glfwCreateStandardCursor(GLFW_POINTING_HAND_CURSOR);
|
|
_glfwSetCursorOgc(window, (_GLFWcursor*) cursor);
|
|
|
|
return GLFW_TRUE;
|
|
}
|
|
|
|
void _glfwDestroyWindowOgc(_GLFWwindow* window)
|
|
{
|
|
if (window->monitor)
|
|
releaseMonitor(window);
|
|
}
|
|
|
|
void _glfwSetWindowTitleOgc(_GLFWwindow* window, const char* title)
|
|
{
|
|
_glfwInputError(GLFW_FEATURE_UNAVAILABLE, _glfwUnimplementedFmt,
|
|
"setting the window title");
|
|
}
|
|
|
|
void _glfwSetWindowIconOgc(_GLFWwindow* window,
|
|
int count, const GLFWimage* images)
|
|
{
|
|
_glfwInputError(GLFW_FEATURE_UNAVAILABLE, _glfwUnimplementedFmt,
|
|
"setting the window icon");
|
|
}
|
|
|
|
void _glfwGetWindowPosOgc(_GLFWwindow* window, int* xpos, int* ypos)
|
|
{
|
|
_glfwInputError(GLFW_FEATURE_UNAVAILABLE, _glfwUnimplementedFmt,
|
|
"getting the window position");
|
|
}
|
|
|
|
void _glfwSetWindowPosOgc(_GLFWwindow* window, int xpos, int ypos)
|
|
{
|
|
_glfwInputError(GLFW_FEATURE_UNAVAILABLE, _glfwUnimplementedFmt,
|
|
"setting the window position");
|
|
}
|
|
|
|
void _glfwGetWindowSizeOgc(_GLFWwindow* window, int* width, int* height)
|
|
{
|
|
if (width)
|
|
*width = window->ogc.width;
|
|
if (height)
|
|
*height = window->ogc.height;
|
|
}
|
|
|
|
void _glfwSetWindowSizeOgc(_GLFWwindow* window, int width, int height)
|
|
{
|
|
fprintf(stderr, "%s:%d %s %dx%d\n", __FILE__, __LINE__, __func__, width, height);
|
|
if (window->monitor)
|
|
{
|
|
}
|
|
else
|
|
{
|
|
_glfwInputWindowDamage(window);
|
|
}
|
|
}
|
|
|
|
void _glfwSetWindowSizeLimitsOgc(_GLFWwindow* window,
|
|
int minwidth, int minheight,
|
|
int maxwidth, int maxheight)
|
|
{
|
|
_glfwInputError(GLFW_FEATURE_UNAVAILABLE, _glfwUnimplementedFmt,
|
|
"setting the size limits");
|
|
}
|
|
|
|
void _glfwSetWindowAspectRatioOgc(_GLFWwindow* window, int numer, int denom)
|
|
{
|
|
_glfwInputError(GLFW_FEATURE_UNAVAILABLE, _glfwUnimplementedFmt,
|
|
"setting the aspect ratio");
|
|
}
|
|
|
|
void _glfwGetFramebufferSizeOgc(_GLFWwindow* window, int* width, int* height)
|
|
{
|
|
if (width)
|
|
*width = window->monitor->ogc.ogcMode->fbWidth;
|
|
if (height)
|
|
*height = window->monitor->ogc.ogcMode->efbHeight;;
|
|
}
|
|
|
|
void _glfwGetWindowFrameSizeOgc(_GLFWwindow* window,
|
|
int* left, int* top,
|
|
int* right, int* bottom)
|
|
{
|
|
*left = *top = *right = *bottom = 0;
|
|
}
|
|
|
|
void _glfwGetWindowContentScaleOgc(_GLFWwindow* window,
|
|
float* xscale, float* yscale)
|
|
{
|
|
if (xscale)
|
|
*xscale = 1.0f;
|
|
if (yscale)
|
|
*yscale = 1.0f;
|
|
}
|
|
|
|
void _glfwIconifyWindowOgc(_GLFWwindow* window)
|
|
{
|
|
_glfwInputError(GLFW_FEATURE_UNAVAILABLE, _glfwUnimplementedFmt,
|
|
"iconifying the window");
|
|
}
|
|
|
|
void _glfwRestoreWindowOgc(_GLFWwindow* window)
|
|
{
|
|
_glfwInputError(GLFW_FEATURE_UNAVAILABLE, _glfwUnimplementedFmt,
|
|
"restoring the window");
|
|
}
|
|
|
|
void _glfwMaximizeWindowOgc(_GLFWwindow* window)
|
|
{
|
|
}
|
|
|
|
void _glfwShowWindowOgc(_GLFWwindow* window)
|
|
{
|
|
}
|
|
|
|
void _glfwHideWindowOgc(_GLFWwindow* window)
|
|
{
|
|
}
|
|
|
|
void _glfwRequestWindowAttentionOgc(_GLFWwindow* window)
|
|
{
|
|
}
|
|
|
|
void _glfwFocusWindowOgc(_GLFWwindow* window)
|
|
{
|
|
}
|
|
|
|
void _glfwSetWindowMonitorOgc(_GLFWwindow* window,
|
|
_GLFWmonitor* monitor,
|
|
int xpos, int ypos,
|
|
int width, int height,
|
|
int refreshRate)
|
|
{
|
|
}
|
|
|
|
GLFWbool _glfwWindowFocusedOgc(_GLFWwindow* window)
|
|
{
|
|
return GLFW_TRUE;
|
|
}
|
|
|
|
GLFWbool _glfwWindowIconifiedOgc(_GLFWwindow* window)
|
|
{
|
|
return GLFW_FALSE;
|
|
}
|
|
|
|
GLFWbool _glfwWindowVisibleOgc(_GLFWwindow* window)
|
|
{
|
|
return GLFW_TRUE;
|
|
}
|
|
|
|
GLFWbool _glfwWindowMaximizedOgc(_GLFWwindow* window)
|
|
{
|
|
return GLFW_TRUE;
|
|
}
|
|
|
|
GLFWbool _glfwWindowHoveredOgc(_GLFWwindow* window)
|
|
{
|
|
return window->ogc.hovered;
|
|
}
|
|
|
|
GLFWbool _glfwFramebufferTransparentOgc(_GLFWwindow* window)
|
|
{
|
|
return GLFW_FALSE;
|
|
}
|
|
|
|
void _glfwSetWindowResizableOgc(_GLFWwindow* window, GLFWbool enabled)
|
|
{
|
|
}
|
|
|
|
void _glfwSetWindowDecoratedOgc(_GLFWwindow* window, GLFWbool enabled)
|
|
{
|
|
}
|
|
|
|
void _glfwSetWindowFloatingOgc(_GLFWwindow* window, GLFWbool enabled)
|
|
{
|
|
_glfwInputError(GLFW_FEATURE_UNAVAILABLE, _glfwUnimplementedFmt,
|
|
"making a window floating");
|
|
}
|
|
|
|
void _glfwSetWindowMousePassthroughOgc(_GLFWwindow* window, GLFWbool enabled)
|
|
{
|
|
}
|
|
|
|
float _glfwGetWindowOpacityOgc(_GLFWwindow* window)
|
|
{
|
|
return 1.f;
|
|
}
|
|
|
|
void _glfwSetWindowOpacityOgc(_GLFWwindow* window, float opacity)
|
|
{
|
|
_glfwInputError(GLFW_FEATURE_UNAVAILABLE, _glfwUnimplementedFmt,
|
|
"setting the window opacity");
|
|
}
|
|
|
|
void _glfwSetRawMouseMotionOgc(_GLFWwindow* window, GLFWbool enabled)
|
|
{
|
|
}
|
|
|
|
GLFWbool _glfwRawMouseMotionSupportedOgc(void)
|
|
{
|
|
return GLFW_FALSE;
|
|
}
|
|
|
|
#ifdef __wii__
|
|
static void handleWiimoteCursorOgc(_GLFWwindow* window)
|
|
{
|
|
WPADData *data = WPAD_Data(0);
|
|
float x, y;
|
|
|
|
GLFWbool mouseActive = !!data->ir.valid;
|
|
if (mouseActive != window->ogc.hovered) {
|
|
window->ogc.hovered = mouseActive;
|
|
_glfwInputCursorEnter(window, mouseActive);
|
|
}
|
|
|
|
if (!mouseActive) return;
|
|
|
|
x = data->ir.x * window->ogc.width / data->ir.vres[0];
|
|
y = data->ir.y * window->ogc.height / data->ir.vres[1];
|
|
_glfwInputCursorPos(window, x, y);
|
|
|
|
if (data->btns_d & WPAD_BUTTON_A)
|
|
_glfwInputMouseClick(window, GLFW_MOUSE_BUTTON_1, GLFW_PRESS, 0);
|
|
if (data->btns_u & WPAD_BUTTON_A)
|
|
_glfwInputMouseClick(window, GLFW_MOUSE_BUTTON_1, GLFW_RELEASE, 0);
|
|
if (data->btns_d & WPAD_BUTTON_B)
|
|
_glfwInputMouseClick(window, GLFW_MOUSE_BUTTON_2, GLFW_PRESS, 0);
|
|
if (data->btns_u & WPAD_BUTTON_B)
|
|
_glfwInputMouseClick(window, GLFW_MOUSE_BUTTON_2, GLFW_RELEASE, 0);
|
|
}
|
|
#endif
|
|
|
|
void _glfwPollEventsOgc(void)
|
|
{
|
|
//fprintf(stderr, "Polling for events %d\n", 0);
|
|
GLFWbool hasEvents = GLFW_FALSE;
|
|
|
|
if (_glfwPollJoysticksOgc()) {
|
|
hasEvents = GLFW_TRUE;
|
|
#ifdef __wii__
|
|
/* Use the first wiimote as mouse */
|
|
if (_glfw.windowListHead)
|
|
handleWiimoteCursorOgc(_glfw.windowListHead);
|
|
#endif
|
|
}
|
|
|
|
}
|
|
|
|
void _glfwWaitEventsOgc(void)
|
|
{
|
|
// TODO: check if events were produced or sleep?
|
|
_glfwPollEventsOgc();
|
|
}
|
|
|
|
void _glfwWaitEventsTimeoutOgc(double timeout)
|
|
{
|
|
// TODO: check if events were produced or sleep?
|
|
_glfwPollEventsOgc();
|
|
}
|
|
|
|
void _glfwPostEmptyEventOgc(void)
|
|
{
|
|
}
|
|
|
|
void _glfwGetCursorPosOgc(_GLFWwindow* window, double* xpos, double* ypos)
|
|
{
|
|
if (xpos)
|
|
*xpos = window->virtualCursorPosX;
|
|
if (ypos)
|
|
*ypos = window->virtualCursorPosY;
|
|
}
|
|
|
|
void _glfwSetCursorPosOgc(_GLFWwindow* window, double x, double y)
|
|
{
|
|
_glfwInputError(GLFW_FEATURE_UNAVAILABLE, _glfwUnimplementedFmt,
|
|
"setting the cursor position");
|
|
}
|
|
|
|
void _glfwSetCursorModeOgc(_GLFWwindow* window, int mode)
|
|
{
|
|
// TODO
|
|
}
|
|
|
|
const char* _glfwGetScancodeNameOgc(int scancode)
|
|
{
|
|
static char name[10];
|
|
|
|
name[0] = name[1] = '\0';
|
|
|
|
switch (scancode) {
|
|
case KS_Return: name[0] = '\n'; break;
|
|
case KS_Escape: return "ESC";
|
|
default:
|
|
keysym_to_utf8(scancode, name);
|
|
}
|
|
|
|
return name;
|
|
}
|
|
|
|
int _glfwGetKeyScancodeOgc(int key)
|
|
{
|
|
return _glfw.ogc.scancodes[key];
|
|
}
|
|
|
|
GLFWbool _glfwCreateCursorOgc(_GLFWcursor* cursor,
|
|
const GLFWimage* image,
|
|
int xhot, int yhot)
|
|
{
|
|
void* texels = createRGBAtexture(image);
|
|
if (!texels) return GLFW_FALSE;
|
|
|
|
cursor->ogc.xhot = xhot;
|
|
cursor->ogc.yhot = yhot;
|
|
|
|
GX_InvalidateTexAll();
|
|
GX_InitTexObj(&cursor->ogc.texobj, texels,
|
|
image->width, image->height,
|
|
GX_TF_RGBA8, GX_CLAMP, GX_CLAMP, GX_FALSE);
|
|
GX_InitTexObjLOD(&cursor->ogc.texobj, GX_LINEAR, GX_LINEAR,
|
|
0.0f, 0.0f, 0.0f, 0, 0, GX_ANISO_1);
|
|
|
|
return GLFW_TRUE;
|
|
}
|
|
|
|
GLFWbool _glfwCreateStandardCursorOgc(_GLFWcursor* cursor, int shape)
|
|
{
|
|
const _GLFWcursorDataOgc* cd = NULL;
|
|
|
|
switch (shape)
|
|
{
|
|
case GLFW_ARROW_CURSOR:
|
|
cd = &OGC_cursor_arrow;
|
|
break;
|
|
case GLFW_POINTING_HAND_CURSOR:
|
|
cd = &OGC_cursor_hand;
|
|
break;
|
|
default:
|
|
return GLFW_FALSE;
|
|
}
|
|
|
|
GLFWimage image = {
|
|
cd->width, cd->height, cd->pixel_data
|
|
};
|
|
return _glfwCreateCursorOgc(cursor, &image,
|
|
cd->hot_x, cd->hot_y);
|
|
}
|
|
|
|
void _glfwDestroyCursorOgc(_GLFWcursor* cursor)
|
|
{
|
|
void *data = GX_GetTexObjData(&cursor->ogc.texobj);
|
|
if (data != 0)
|
|
free(MEM_PHYSICAL_TO_K0(data));
|
|
|
|
}
|
|
|
|
void _glfwSetCursorOgc(_GLFWwindow* window, _GLFWcursor* cursor)
|
|
{
|
|
window->ogc.currentCursor = cursor;
|
|
}
|
|
|
|
void _glfwSetClipboardStringOgc(const char* string)
|
|
{
|
|
}
|
|
|
|
const char* _glfwGetClipboardStringOgc(void)
|
|
{
|
|
return NULL;
|
|
}
|
|
|
|
EGLenum _glfwGetEGLPlatformOgc(EGLint** attribs)
|
|
{
|
|
return EGL_PLATFORM_ANGLE_ANGLE;
|
|
}
|
|
|
|
EGLNativeDisplayType _glfwGetEGLNativeDisplayOgc(void)
|
|
{
|
|
return EGL_DEFAULT_DISPLAY;
|
|
}
|
|
|
|
EGLNativeWindowType _glfwGetEGLNativeWindowOgc(_GLFWwindow* window)
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
void _glfwGetRequiredInstanceExtensionsOgc(char** extensions)
|
|
{
|
|
}
|
|
|
|
GLFWbool _glfwGetPhysicalDevicePresentationSupportOgc(VkInstance instance,
|
|
VkPhysicalDevice device,
|
|
uint32_t queuefamily)
|
|
{
|
|
return GLFW_FALSE;
|
|
}
|
|
|
|
VkResult _glfwCreateWindowSurfaceOgc(VkInstance instance,
|
|
_GLFWwindow* window,
|
|
const VkAllocationCallbacks* allocator,
|
|
VkSurfaceKHR* surface)
|
|
{
|
|
return VK_ERROR_EXTENSION_NOT_PRESENT;
|
|
}
|
|
|
|
#endif // _GLFW_OGC
|