1
0
mirror of https://github.com/libretro/RetroArch synced 2024-07-03 00:38:44 +00:00

odroidgo2: patched DRM driver

This commit is contained in:
natinusala 2020-02-27 10:22:35 +01:00
parent a75059f94b
commit f00fb6d1ea
18 changed files with 2923 additions and 41 deletions

View File

@ -2112,6 +2112,9 @@ endif
ifeq ($(HAVE_ODROIDGO2), 1)
DEFINES += -DHAVE_ODROIDGO2
LIBS += -lrk_rga
LIBS += -lrga
INCLUDE_DIRS += -I$(DEPS_DIR)/libgo2/include
OBJ += $(DEPS_DIR)/libgo2/src/display.o \
$(DEPS_DIR)/libgo2/src/queue.o
endif
##################################

16
deps/libgo2/LICENSE vendored Normal file
View File

@ -0,0 +1,16 @@
libgo2 - Support library for the ODROID-GO Advance
Copyright (C) 2020 OtherCrashOverride
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.1 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, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA

34
deps/libgo2/Makefile vendored Normal file
View File

@ -0,0 +1,34 @@
# GNU Make solution makefile autogenerated by Premake
# Type "make help" for usage help
ifndef config
config=debug
endif
export config
PROJECTS := go2
.PHONY: all clean help $(PROJECTS)
all: $(PROJECTS)
go2:
@echo "==== Building go2 ($(config)) ===="
@${MAKE} --no-print-directory -C build/gmake -f Makefile
clean:
@${MAKE} --no-print-directory -C build/gmake -f Makefile clean
help:
@echo "Usage: make [config=name] [target]"
@echo ""
@echo "CONFIGURATIONS:"
@echo " debug"
@echo " release"
@echo ""
@echo "TARGETS:"
@echo " all (default)"
@echo " clean"
@echo " go2"
@echo ""
@echo "For more information, see http://industriousone.com/premake/quick-start"

1
deps/libgo2/README.md vendored Normal file
View File

@ -0,0 +1 @@
libgo2 - Support library for the ODROID-GO Advance

144
deps/libgo2/build/gmake/Makefile vendored Normal file
View File

@ -0,0 +1,144 @@
# GNU Make project makefile autogenerated by Premake
ifndef config
config=debug
endif
ifndef verbose
SILENT = @
endif
ifndef CC
CC = gcc
endif
ifndef CXX
CXX = g++
endif
ifndef AR
AR = ar
endif
ifeq ($(config),debug)
OBJDIR = obj/Debug
TARGETDIR = ../..
TARGET = $(TARGETDIR)/libgo2.so
DEFINES += -DDEBUG
INCLUDES += -I/usr/include/libdrm
CPPFLAGS += -MMD -MP $(DEFINES) $(INCLUDES)
CFLAGS += $(CPPFLAGS) $(ARCH) -g -fPIC -Wall
CXXFLAGS += $(CFLAGS)
LDFLAGS += -shared -lopenal -lEGL -levdev -lgbm -lpthread -ldrm -lm -lrga -lpng -lasound
LIBS +=
RESFLAGS += $(DEFINES) $(INCLUDES)
LDDEPS +=
LINKCMD = $(CC) -o $(TARGET) $(OBJECTS) $(LDFLAGS) $(RESOURCES) $(ARCH) $(LIBS)
define PREBUILDCMDS
endef
define PRELINKCMDS
endef
define POSTBUILDCMDS
endef
endif
ifeq ($(config),release)
OBJDIR = obj/Release
TARGETDIR = ../..
TARGET = $(TARGETDIR)/libgo2.so
DEFINES += -DNDEBUG
INCLUDES += -I/usr/include/libdrm
CPPFLAGS += -MMD -MP $(DEFINES) $(INCLUDES)
CFLAGS += $(CPPFLAGS) $(ARCH) -O2 -fPIC -Wall
CXXFLAGS += $(CFLAGS)
LDFLAGS += -s -shared -lopenal -lEGL -levdev -lgbm -lpthread -ldrm -lm -lrga -lpng -lasound
LIBS +=
RESFLAGS += $(DEFINES) $(INCLUDES)
LDDEPS +=
LINKCMD = $(CC) -o $(TARGET) $(OBJECTS) $(LDFLAGS) $(RESOURCES) $(ARCH) $(LIBS)
define PREBUILDCMDS
endef
define PRELINKCMDS
endef
define POSTBUILDCMDS
endef
endif
OBJECTS := \
$(OBJDIR)/audio.o \
$(OBJDIR)/input.o \
$(OBJDIR)/display.o \
$(OBJDIR)/queue.o \
RESOURCES := \
SHELLTYPE := msdos
ifeq (,$(ComSpec)$(COMSPEC))
SHELLTYPE := posix
endif
ifeq (/bin,$(findstring /bin,$(SHELL)))
SHELLTYPE := posix
endif
.PHONY: clean prebuild prelink
all: $(TARGETDIR) $(OBJDIR) prebuild prelink $(TARGET)
@:
$(TARGET): $(GCH) $(OBJECTS) $(LDDEPS) $(RESOURCES)
@echo Linking go2
$(SILENT) $(LINKCMD)
$(POSTBUILDCMDS)
$(TARGETDIR):
@echo Creating $(TARGETDIR)
ifeq (posix,$(SHELLTYPE))
$(SILENT) mkdir -p $(TARGETDIR)
else
$(SILENT) mkdir $(subst /,\\,$(TARGETDIR))
endif
$(OBJDIR):
@echo Creating $(OBJDIR)
ifeq (posix,$(SHELLTYPE))
$(SILENT) mkdir -p $(OBJDIR)
else
$(SILENT) mkdir $(subst /,\\,$(OBJDIR))
endif
clean:
@echo Cleaning go2
ifeq (posix,$(SHELLTYPE))
$(SILENT) rm -f $(TARGET)
$(SILENT) rm -rf $(OBJDIR)
else
$(SILENT) if exist $(subst /,\\,$(TARGET)) del $(subst /,\\,$(TARGET))
$(SILENT) if exist $(subst /,\\,$(OBJDIR)) rmdir /s /q $(subst /,\\,$(OBJDIR))
endif
prebuild:
$(PREBUILDCMDS)
prelink:
$(PRELINKCMDS)
ifneq (,$(PCH))
$(GCH): $(PCH)
@echo $(notdir $<)
-$(SILENT) cp $< $(OBJDIR)
$(SILENT) $(CC) $(CFLAGS) -o "$@" -c "$<"
endif
$(OBJDIR)/audio.o: ../../src/audio.c
@echo $(notdir $<)
$(SILENT) $(CC) $(CFLAGS) -o "$@" -c "$<"
$(OBJDIR)/input.o: ../../src/input.c
@echo $(notdir $<)
$(SILENT) $(CC) $(CFLAGS) -o "$@" -c "$<"
$(OBJDIR)/display.o: ../../src/display.c
@echo $(notdir $<)
$(SILENT) $(CC) $(CFLAGS) -o "$@" -c "$<"
$(OBJDIR)/queue.o: ../../src/queue.c
@echo $(notdir $<)
$(SILENT) $(CC) $(CFLAGS) -o "$@" -c "$<"
-include $(OBJECTS:%.o=%.d)

105
deps/libgo2/include/go2/display.h vendored Normal file
View File

@ -0,0 +1,105 @@
#pragma once
/*
libgo2 - Support library for the ODROID-GO Advance
Copyright (C) 2020 OtherCrashOverride
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.1 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, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include <stdint.h>
typedef struct go2_display go2_display_t;
typedef struct go2_surface go2_surface_t;
typedef struct go2_frame_buffer go2_frame_buffer_t;
typedef struct go2_presenter go2_presenter_t;
typedef enum go2_rotation
{
GO2_ROTATION_DEGREES_0 = 0,
GO2_ROTATION_DEGREES_90,
GO2_ROTATION_DEGREES_180,
GO2_ROTATION_DEGREES_270
} go2_rotation_t;
typedef struct go2_context_attributes
{
int major;
int minor;
int red_bits;
int green_bits;
int blue_bits;
int alpha_bits;
int depth_bits;
int stencil_bits;
} go2_context_attributes_t;
typedef struct go2_context go2_context_t;
#ifdef __cplusplus
extern "C" {
#endif
go2_display_t* go2_display_create();
void go2_display_destroy(go2_display_t* display);
int go2_display_width_get(go2_display_t* display);
int go2_display_height_get(go2_display_t* display);
void go2_display_present(go2_display_t* display, go2_frame_buffer_t* frame_buffer);
uint32_t go2_display_backlight_get(go2_display_t* display);
void go2_display_backlight_set(go2_display_t* display, uint32_t value);
int go2_drm_format_get_bpp(uint32_t format);
go2_surface_t* go2_surface_create(go2_display_t* display, int width, int height, uint32_t format);
void go2_surface_destroy(go2_surface_t* surface);
int go2_surface_width_get(go2_surface_t* surface);
int go2_surface_height_get(go2_surface_t* surface);
uint32_t go2_surface_format_get(go2_surface_t* surface);
int go2_surface_stride_get(go2_surface_t* surface);
go2_display_t* go2_surface_display_get(go2_surface_t* surface);
int go2_surface_prime_fd(go2_surface_t* surface);
void* go2_surface_map(go2_surface_t* surface);
void go2_surface_unmap(go2_surface_t* surface);
void go2_surface_blit(go2_surface_t* srcSurface, int srcX, int srcY, int srcWidth, int srcHeight,
go2_surface_t* dstSurface, int dstX, int dstY, int dstWidth, int dstHeight,
go2_rotation_t rotation);
int go2_surface_save_as_png(go2_surface_t* surface, const char* filename);
go2_frame_buffer_t* go2_frame_buffer_create(go2_surface_t* surface);
void go2_frame_buffer_destroy(go2_frame_buffer_t* frame_buffer);
go2_surface_t* go2_frame_buffer_surface_get(go2_frame_buffer_t* frame_buffer);
go2_presenter_t* go2_presenter_create(go2_display_t* display, uint32_t format, uint32_t background_color);
void go2_presenter_destroy(go2_presenter_t* presenter);
void go2_presenter_post(go2_presenter_t* presenter, go2_surface_t* surface, int srcX, int srcY, int srcWidth, int srcHeight, int dstX, int dstY, int dstWidth, int dstHeight, go2_rotation_t rotation);
go2_context_t* go2_context_create(go2_display_t* display, int width, int height, const go2_context_attributes_t* attributes);
void go2_context_destroy(go2_context_t* context);
void* go2_context_egldisplay_get(go2_context_t* context);
void go2_context_make_current(go2_context_t* context);
void go2_context_swap_buffers(go2_context_t* context);
go2_surface_t* go2_context_surface_lock(go2_context_t* context);
void go2_context_surface_unlock(go2_context_t* context, go2_surface_t* surface);
#ifdef __cplusplus
}
#endif

37
deps/libgo2/include/go2/queue.h vendored Normal file
View File

@ -0,0 +1,37 @@
#pragma once
/*
libgo2 - Support library for the ODROID-GO Advance
Copyright (C) 2020 OtherCrashOverride
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.1 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, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
typedef struct go2_queue go2_queue_t;
#ifdef __cplusplus
extern "C" {
#endif
go2_queue_t* go2_queue_create(int capacity);
int go2_queue_count_get(go2_queue_t* queue);
void go2_queue_push(go2_queue_t* queue, void* value);
void* go2_queue_pop(go2_queue_t* queue);
void go2_queue_destroy(go2_queue_t* queue);
#ifdef __cplusplus
}
#endif

22
deps/libgo2/premake4.lua vendored Normal file
View File

@ -0,0 +1,22 @@
#!lua
local output = "./build/" .. _ACTION
solution "go2_solution"
configurations { "Debug", "Release" }
project "go2"
location (output)
kind "SharedLib"
language "C"
files { "src/**.h", "src/**.c" }
buildoptions { "-Wall" }
linkoptions { "-lopenal -lEGL -levdev -lgbm -lpthread -ldrm -lm -lrga -lpng -lasound" }
includedirs { "/usr/include/libdrm" }
configuration "Debug"
flags { "Symbols" }
defines { "DEBUG" }
configuration "Release"
flags { "Optimize" }
defines { "NDEBUG" }

287
deps/libgo2/src/audio.c vendored Normal file
View File

@ -0,0 +1,287 @@
/*
libgo2 - Support library for the ODROID-GO Advance
Copyright (C) 2020 OtherCrashOverride
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.1 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, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include "audio.h"
#include <AL/al.h>
#include <AL/alc.h>
#include <AL/alext.h>
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <alsa/asoundlib.h>
#include <alsa/mixer.h>
#define SOUND_SAMPLES_SIZE (2048)
#define SOUND_CHANNEL_COUNT 2
typedef struct go2_audio
{
ALsizei frequency;
ALCdevice *device;
ALCcontext *context;
ALuint source;
bool isAudioInitialized;
} go2_audio_t;
go2_audio_t* go2_audio_create(int frequency)
{
go2_audio_t* result = malloc(sizeof(*result));
if (!result)
{
printf("malloc failed.\n");
goto out;
}
memset(result, 0, sizeof(*result));
result->frequency = frequency;
result->device = alcOpenDevice(NULL);
if (!result->device)
{
printf("alcOpenDevice failed.\n");
goto err_00;
}
result->context = alcCreateContext(result->device, NULL);
if (!alcMakeContextCurrent(result->context))
{
printf("alcMakeContextCurrent failed.\n");
goto err_01;
}
alGenSources((ALuint)1, &result->source);
alSourcef(result->source, AL_PITCH, 1);
alSourcef(result->source, AL_GAIN, 1);
alSource3f(result->source, AL_POSITION, 0, 0, 0);
alSource3f(result->source, AL_VELOCITY, 0, 0, 0);
alSourcei(result->source, AL_LOOPING, AL_FALSE);
//memset(audioBuffer, 0, AUDIOBUFFER_LENGTH * sizeof(short));
const int BUFFER_COUNT = 4;
for (int i = 0; i < BUFFER_COUNT; ++i)
{
ALuint buffer;
alGenBuffers((ALuint)1, &buffer);
alBufferData(buffer, AL_FORMAT_STEREO16, NULL, 0, frequency);
alSourceQueueBuffers(result->source, 1, &buffer);
}
alSourcePlay(result->source);
result->isAudioInitialized = true;
// testing
//uint32_t vol = go2_audio_volume_get(result);
//printf("audio: vol=%d\n", vol);
//go2_audio_path_get(result);
return result;
err_01:
alcCloseDevice(result->device);
err_00:
free(result);
out:
return NULL;
}
void go2_audio_destroy(go2_audio_t* audio)
{
alDeleteSources(1, &audio->source);
alcDestroyContext(audio->context);
alcCloseDevice(audio->device);
free(audio);
}
void go2_audio_submit(go2_audio_t* audio, const short* data, int frames)
{
if (!audio || !audio->isAudioInitialized) return;
if (!alcMakeContextCurrent(audio->context))
{
printf("alcMakeContextCurrent failed.\n");
return;
}
ALint processed = 0;
while(!processed)
{
alGetSourceiv(audio->source, AL_BUFFERS_PROCESSED, &processed);
if (!processed)
{
sleep(0);
//printf("Audio overflow.\n");
//return;
}
}
ALuint openALBufferID;
alSourceUnqueueBuffers(audio->source, 1, &openALBufferID);
ALuint format = AL_FORMAT_STEREO16;
int dataByteLength = frames * sizeof(short) * SOUND_CHANNEL_COUNT;
alBufferData(openALBufferID, format, data, dataByteLength, audio->frequency);
alSourceQueueBuffers(audio->source, 1, &openALBufferID);
ALint result;
alGetSourcei(audio->source, AL_SOURCE_STATE, &result);
if (result != AL_PLAYING)
{
alSourcePlay(audio->source);
}
}
uint32_t go2_audio_volume_get(go2_audio_t* audio)
{
snd_mixer_t *handle;
snd_mixer_selem_id_t *sid;
const char *card = "default";
const char *selem_name = "Playback";
snd_mixer_open(&handle, 0);
snd_mixer_attach(handle, card);
snd_mixer_selem_register(handle, NULL, NULL);
snd_mixer_load(handle);
snd_mixer_selem_id_alloca(&sid);
snd_mixer_selem_id_set_index(sid, 0);
snd_mixer_selem_id_set_name(sid, selem_name);
snd_mixer_elem_t* elem = snd_mixer_find_selem(handle, sid);
long min;
long max;
snd_mixer_selem_get_playback_volume_range(elem, &min, &max);
//snd_mixer_selem_set_playback_volume_all(elem, value / 100.0f * max);
long volume;
snd_mixer_selem_get_playback_volume(elem, SND_MIXER_SCHN_MONO, &volume);
snd_mixer_close(handle);
uint32_t result = volume / (float)max * 100.0f;
//printf("volume: min=%ld, max=%ld, volume=%ld, result=%d\n", min, max, volume, result);
return result;
}
void go2_audio_volume_set(go2_audio_t* audio, uint32_t value)
{
// https://gist.github.com/wolfg1969/3575700
snd_mixer_t *handle;
snd_mixer_selem_id_t *sid;
const char *card = "default";
const char *selem_name = "Playback";
snd_mixer_open(&handle, 0);
snd_mixer_attach(handle, card);
snd_mixer_selem_register(handle, NULL, NULL);
snd_mixer_load(handle);
snd_mixer_selem_id_alloca(&sid);
snd_mixer_selem_id_set_index(sid, 0);
snd_mixer_selem_id_set_name(sid, selem_name);
snd_mixer_elem_t* elem = snd_mixer_find_selem(handle, sid);
long min;
long max;
snd_mixer_selem_get_playback_volume_range(elem, &min, &max);
//printf("volume: min=%ld, max=%ld\n", min, max);
snd_mixer_selem_set_playback_volume_all(elem, value / 100.0f * max);
snd_mixer_close(handle);
}
go2_audio_path_t go2_audio_path_get(go2_audio_t* audio)
{
snd_mixer_t *handle;
snd_mixer_selem_id_t *sid;
const char *card = "default";
const char *selem_name = "Playback Path";
snd_mixer_open(&handle, 0);
snd_mixer_attach(handle, card);
snd_mixer_selem_register(handle, NULL, NULL);
snd_mixer_load(handle);
snd_mixer_selem_id_alloca(&sid);
snd_mixer_selem_id_set_index(sid, 0);
snd_mixer_selem_id_set_name(sid, selem_name);
snd_mixer_elem_t* elem = snd_mixer_find_selem(handle, sid);
unsigned int value;
snd_mixer_selem_get_enum_item(elem, SND_MIXER_SCHN_MONO, &value);
// char name[128];
// snd_mixer_selem_get_enum_item_name(elem, value, 128, name);
// printf("audio path: value=%d [%s]\n", value, name);
snd_mixer_close(handle);
return (go2_audio_path_t)value;
}
void go2_audio_path_set(go2_audio_t* audio, go2_audio_path_t value)
{
snd_mixer_t *handle;
snd_mixer_selem_id_t *sid;
const char *card = "default";
const char *selem_name = "Playback Path";
snd_mixer_open(&handle, 0);
snd_mixer_attach(handle, card);
snd_mixer_selem_register(handle, NULL, NULL);
snd_mixer_load(handle);
snd_mixer_selem_id_alloca(&sid);
snd_mixer_selem_id_set_index(sid, 0);
snd_mixer_selem_id_set_name(sid, selem_name);
snd_mixer_elem_t* elem = snd_mixer_find_selem(handle, sid);
snd_mixer_selem_set_enum_item(elem, SND_MIXER_SCHN_MONO, (unsigned int)value);
snd_mixer_close(handle);
}

52
deps/libgo2/src/audio.h vendored Normal file
View File

@ -0,0 +1,52 @@
#pragma once
/*
libgo2 - Support library for the ODROID-GO Advance
Copyright (C) 2020 OtherCrashOverride
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.1 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, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include <stdint.h>
typedef struct go2_audio go2_audio_t;
typedef enum
{
Audio_Path_Off = 0,
Audio_Path_Speaker,
Audio_Path_Headphones,
Audio_Path_SpeakerAndHeadphones,
Audio_Path_MAX = 0x7fffffff
} go2_audio_path_t;
#ifdef __cplusplus
extern "C" {
#endif
go2_audio_t* go2_audio_create(int frequency);
void go2_audio_destroy(go2_audio_t* audio);
void go2_audio_submit(go2_audio_t* audio, const short* data, int frames);
uint32_t go2_audio_volume_get(go2_audio_t* audio);
void go2_audio_volume_set(go2_audio_t* audio, uint32_t value);
go2_audio_path_t go2_audio_path_get(go2_audio_t* audio);
void go2_audio_path_set(go2_audio_t* audio, go2_audio_path_t value);
#ifdef __cplusplus
}
#endif

1367
deps/libgo2/src/display.c vendored Normal file

File diff suppressed because it is too large Load Diff

105
deps/libgo2/src/display.h vendored Normal file
View File

@ -0,0 +1,105 @@
#pragma once
/*
libgo2 - Support library for the ODROID-GO Advance
Copyright (C) 2020 OtherCrashOverride
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.1 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, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include <stdint.h>
typedef struct go2_display go2_display_t;
typedef struct go2_surface go2_surface_t;
typedef struct go2_frame_buffer go2_frame_buffer_t;
typedef struct go2_presenter go2_presenter_t;
typedef enum go2_rotation
{
GO2_ROTATION_DEGREES_0 = 0,
GO2_ROTATION_DEGREES_90,
GO2_ROTATION_DEGREES_180,
GO2_ROTATION_DEGREES_270
} go2_rotation_t;
typedef struct go2_context_attributes
{
int major;
int minor;
int red_bits;
int green_bits;
int blue_bits;
int alpha_bits;
int depth_bits;
int stencil_bits;
} go2_context_attributes_t;
typedef struct go2_context go2_context_t;
#ifdef __cplusplus
extern "C" {
#endif
go2_display_t* go2_display_create();
void go2_display_destroy(go2_display_t* display);
int go2_display_width_get(go2_display_t* display);
int go2_display_height_get(go2_display_t* display);
void go2_display_present(go2_display_t* display, go2_frame_buffer_t* frame_buffer);
uint32_t go2_display_backlight_get(go2_display_t* display);
void go2_display_backlight_set(go2_display_t* display, uint32_t value);
int go2_drm_format_get_bpp(uint32_t format);
go2_surface_t* go2_surface_create(go2_display_t* display, int width, int height, uint32_t format);
void go2_surface_destroy(go2_surface_t* surface);
int go2_surface_width_get(go2_surface_t* surface);
int go2_surface_height_get(go2_surface_t* surface);
uint32_t go2_surface_format_get(go2_surface_t* surface);
int go2_surface_stride_get(go2_surface_t* surface);
go2_display_t* go2_surface_display_get(go2_surface_t* surface);
int go2_surface_prime_fd(go2_surface_t* surface);
void* go2_surface_map(go2_surface_t* surface);
void go2_surface_unmap(go2_surface_t* surface);
void go2_surface_blit(go2_surface_t* srcSurface, int srcX, int srcY, int srcWidth, int srcHeight,
go2_surface_t* dstSurface, int dstX, int dstY, int dstWidth, int dstHeight,
go2_rotation_t rotation);
int go2_surface_save_as_png(go2_surface_t* surface, const char* filename);
go2_frame_buffer_t* go2_frame_buffer_create(go2_surface_t* surface);
void go2_frame_buffer_destroy(go2_frame_buffer_t* frame_buffer);
go2_surface_t* go2_frame_buffer_surface_get(go2_frame_buffer_t* frame_buffer);
go2_presenter_t* go2_presenter_create(go2_display_t* display, uint32_t format, uint32_t background_color);
void go2_presenter_destroy(go2_presenter_t* presenter);
void go2_presenter_post(go2_presenter_t* presenter, go2_surface_t* surface, int srcX, int srcY, int srcWidth, int srcHeight, int dstX, int dstY, int dstWidth, int dstHeight, go2_rotation_t rotation);
go2_context_t* go2_context_create(go2_display_t* display, int width, int height, const go2_context_attributes_t* attributes);
void go2_context_destroy(go2_context_t* context);
void* go2_context_egldisplay_get(go2_context_t* context);
void go2_context_make_current(go2_context_t* context);
void go2_context_swap_buffers(go2_context_t* context);
go2_surface_t* go2_context_surface_lock(go2_context_t* context);
void go2_context_surface_unlock(go2_context_t* context, go2_surface_t* surface);
#ifdef __cplusplus
}
#endif

371
deps/libgo2/src/input.c vendored Normal file
View File

@ -0,0 +1,371 @@
/*
libgo2 - Support library for the ODROID-GO Advance
Copyright (C) 2020 OtherCrashOverride
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.1 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, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include "input.h"
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <stdint.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <signal.h>
#include <dirent.h>
#include <stdbool.h>
#include <pthread.h>
#include <libevdev-1.0/libevdev/libevdev.h>
#include <linux/limits.h>
#define BATTERY_BUFFER_SIZE (128)
static const char* EVDEV_NAME = "/dev/input/by-path/platform-odroidgo2-joypad-event-joystick";
static const char* BATTERY_STATUS_NAME = "/sys/class/power_supply/battery/status";
static const char* BATTERY_CAPACITY_NAME = "/sys/class/power_supply/battery/capacity";
typedef struct go2_input
{
int fd;
struct libevdev* dev;
go2_gamepad_state_t current_state;
go2_gamepad_state_t pending_state;
pthread_mutex_t gamepadMutex;
pthread_t thread_id;
go2_battery_state_t current_battery;
pthread_t battery_thread;
bool terminating;
} go2_input_t;
static void* battery_task(void* arg)
{
go2_input_t* input = (go2_input_t*)arg;
int fd;
void* result = 0;
char buffer[BATTERY_BUFFER_SIZE + 1];
go2_battery_state_t battery;
memset(&battery, 0, sizeof(battery));
while(!input->terminating)
{
fd = open(BATTERY_STATUS_NAME, O_RDONLY);
if (fd > 0)
{
memset(buffer, 0, BATTERY_BUFFER_SIZE + 1);
ssize_t count = read(fd, buffer, BATTERY_BUFFER_SIZE);
if (count > 0)
{
//printf("BATT: buffer='%s'\n", buffer);
if (buffer[0] == 'D')
{
battery.status = Battery_Status_Discharging;
}
else if (buffer[0] == 'C')
{
battery.status = Battery_Status_Charging;
}
else if (buffer[0] == 'F')
{
battery.status = Battery_Status_Full;
}
else
{
battery.status = Battery_Status_Unknown;
}
}
close(fd);
}
fd = open(BATTERY_CAPACITY_NAME, O_RDONLY);
if (fd > 0)
{
memset(buffer, 0, BATTERY_BUFFER_SIZE + 1);
ssize_t count = read(fd, buffer, BATTERY_BUFFER_SIZE);
if (count > 0)
{
battery.level = atoi(buffer);
}
else
{
battery.level = 0;
}
close(fd);
}
pthread_mutex_lock(&input->gamepadMutex);
input->current_battery = battery;
pthread_mutex_unlock(&input->gamepadMutex);
//printf("BATT: status=%d, level=%d\n", input->current_battery.status, input->current_battery.level);
sleep(1);
}
//printf("BATT: exit.\n");
return result;
}
static void* input_task(void* arg)
{
go2_input_t* input = (go2_input_t*)arg;
if (!input->dev) return NULL;
const int abs_x_max = 512; //libevdev_get_abs_maximum(input->dev, ABS_X);
const int abs_y_max = 512; //libevdev_get_abs_maximum(input->dev, ABS_Y);
//printf("abs: x_max=%d, y_max=%d\n", abs_x_max, abs_y_max);
// Get current state
input->pending_state.dpad.up = libevdev_get_event_value(input->dev, EV_KEY, BTN_DPAD_UP) ? ButtonState_Pressed : ButtonState_Released;
input->pending_state.dpad.down = libevdev_get_event_value(input->dev, EV_KEY, BTN_DPAD_DOWN) ? ButtonState_Pressed : ButtonState_Released;
input->pending_state.dpad.left = libevdev_get_event_value(input->dev, EV_KEY, BTN_DPAD_LEFT) ? ButtonState_Pressed : ButtonState_Released;
input->pending_state.dpad.right = libevdev_get_event_value(input->dev, EV_KEY, BTN_DPAD_RIGHT) ? ButtonState_Pressed : ButtonState_Released;
input->pending_state.buttons.a = libevdev_get_event_value(input->dev, EV_KEY, BTN_EAST) ? ButtonState_Pressed : ButtonState_Released;
input->pending_state.buttons.b = libevdev_get_event_value(input->dev, EV_KEY, BTN_SOUTH) ? ButtonState_Pressed : ButtonState_Released;
input->pending_state.buttons.x = libevdev_get_event_value(input->dev, EV_KEY, BTN_NORTH) ? ButtonState_Pressed : ButtonState_Released;
input->pending_state.buttons.y = libevdev_get_event_value(input->dev, EV_KEY, BTN_WEST) ? ButtonState_Pressed : ButtonState_Released;
input->pending_state.buttons.top_left = libevdev_get_event_value(input->dev, EV_KEY, BTN_TL) ? ButtonState_Pressed : ButtonState_Released;
input->pending_state.buttons.top_right = libevdev_get_event_value(input->dev, EV_KEY, BTN_TR) ? ButtonState_Pressed : ButtonState_Released;
input->current_state.buttons.f1 = libevdev_get_event_value(input->dev, EV_KEY, BTN_TRIGGER_HAPPY1) ? ButtonState_Pressed : ButtonState_Released;
input->current_state.buttons.f2 = libevdev_get_event_value(input->dev, EV_KEY, BTN_TRIGGER_HAPPY2) ? ButtonState_Pressed : ButtonState_Released;
input->current_state.buttons.f3 = libevdev_get_event_value(input->dev, EV_KEY, BTN_TRIGGER_HAPPY3) ? ButtonState_Pressed : ButtonState_Released;
input->current_state.buttons.f4 = libevdev_get_event_value(input->dev, EV_KEY, BTN_TRIGGER_HAPPY4) ? ButtonState_Pressed : ButtonState_Released;
input->current_state.buttons.f5 = libevdev_get_event_value(input->dev, EV_KEY, BTN_TRIGGER_HAPPY5) ? ButtonState_Pressed : ButtonState_Released;
input->current_state.buttons.f5 = libevdev_get_event_value(input->dev, EV_KEY, BTN_TRIGGER_HAPPY6) ? ButtonState_Pressed : ButtonState_Released;
// Events
while (!input->terminating)
{
/* EAGAIN is returned when the queue is empty */
struct input_event ev;
int rc = libevdev_next_event(input->dev, LIBEVDEV_READ_FLAG_BLOCKING, &ev);
if (rc == 0)
{
#if 0
printf("Gamepad Event: %s-%s(%d)=%d\n",
libevdev_event_type_get_name(ev.type),
libevdev_event_code_get_name(ev.type, ev.code), ev.code,
ev.value);
#endif
if (ev.type == EV_KEY)
{
go2_button_state_t state = ev.value ? ButtonState_Pressed : ButtonState_Released;
switch (ev.code)
{
case BTN_DPAD_UP:
input->pending_state.dpad.up = state;
break;
case BTN_DPAD_DOWN:
input->pending_state.dpad.down = state;
break;
case BTN_DPAD_LEFT:
input->pending_state.dpad.left = state;
break;
case BTN_DPAD_RIGHT:
input->pending_state.dpad.right = state;
break;
case BTN_EAST:
input->pending_state.buttons.a = state;
break;
case BTN_SOUTH:
input->pending_state.buttons.b = state;
break;
case BTN_NORTH:
input->pending_state.buttons.x = state;
break;
case BTN_WEST:
input->pending_state.buttons.y = state;
break;
case BTN_TL:
input->pending_state.buttons.top_left = state;
break;
case BTN_TR:
input->pending_state.buttons.top_right = state;
break;
case BTN_TRIGGER_HAPPY1:
input->pending_state.buttons.f1 = state;
break;
case BTN_TRIGGER_HAPPY2:
input->pending_state.buttons.f2 = state;
break;
case BTN_TRIGGER_HAPPY3:
input->pending_state.buttons.f3 = state;
break;
case BTN_TRIGGER_HAPPY4:
input->pending_state.buttons.f4 = state;
break;
case BTN_TRIGGER_HAPPY5:
input->pending_state.buttons.f5 = state;
break;
case BTN_TRIGGER_HAPPY6:
input->pending_state.buttons.f6 = state;
break;
}
}
else if (ev.type == EV_ABS)
{
switch (ev.code)
{
case ABS_X:
input->pending_state.thumb.x = ev.value / (float)abs_x_max;
break;
case ABS_Y:
input->pending_state.thumb.y = ev.value / (float)abs_y_max;
break;
}
}
else if (ev.type == EV_SYN)
{
pthread_mutex_lock(&input->gamepadMutex);
input->current_state = input->pending_state;
pthread_mutex_unlock(&input->gamepadMutex);
}
}
}
return NULL;
}
go2_input_t* go2_input_create()
{
int rc = 1;
go2_input_t* result = malloc(sizeof(*result));
if (!result)
{
printf("malloc failed.\n");
goto out;
}
memset(result, 0, sizeof(*result));
result->fd = open(EVDEV_NAME, O_RDONLY);
if (result->fd < 0)
{
printf("Joystick: No gamepad found.\n");
}
else
{
rc = libevdev_new_from_fd(result->fd, &result->dev);
if (rc < 0) {
printf("Joystick: Failed to init libevdev (%s)\n", strerror(-rc));
goto err_00;
}
memset(&result->current_state, 0, sizeof(result->current_state));
memset(&result->pending_state, 0, sizeof(result->pending_state));
// printf("Input device name: \"%s\"\n", libevdev_get_name(result->dev));
// printf("Input device ID: bus %#x vendor %#x product %#x\n",
// libevdev_get_id_bustype(result->dev),
// libevdev_get_id_vendor(result->dev),
// libevdev_get_id_product(result->dev));
if(pthread_create(&result->thread_id, NULL, input_task, (void*)result) < 0)
{
printf("could not create input_task thread\n");
goto err_01;
}
if(pthread_create(&result->battery_thread, NULL, battery_task, (void*)result) < 0)
{
printf("could not create battery_task thread\n");
}
}
return result;
err_01:
libevdev_free(result->dev);
err_00:
close(result->fd);
free(result);
out:
return NULL;
}
void go2_input_destroy(go2_input_t* input)
{
input->terminating = true;
pthread_cancel(input->thread_id);
pthread_join(input->thread_id, NULL);
pthread_join(input->battery_thread, NULL);
libevdev_free(input->dev);
close(input->fd);
free(input);
}
void go2_input_gamepad_read(go2_input_t* input, go2_gamepad_state_t* outGamepadState)
{
pthread_mutex_lock(&input->gamepadMutex);
*outGamepadState = input->current_state;
pthread_mutex_unlock(&input->gamepadMutex);
}
void go2_input_battery_read(go2_input_t* input, go2_battery_state_t* outBatteryState)
{
pthread_mutex_lock(&input->gamepadMutex);
*outBatteryState = input->current_battery;
pthread_mutex_unlock(&input->gamepadMutex);
}

103
deps/libgo2/src/input.h vendored Normal file
View File

@ -0,0 +1,103 @@
#pragma once
/*
libgo2 - Support library for the ODROID-GO Advance
Copyright (C) 2020 OtherCrashOverride
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.1 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, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include <stdint.h>
typedef struct
{
float x;
float y;
} go2_thumb_t;
typedef enum
{
ButtonState_Released = 0,
ButtonState_Pressed
} go2_button_state_t;
typedef struct
{
go2_button_state_t a;
go2_button_state_t b;
go2_button_state_t x;
go2_button_state_t y;
go2_button_state_t top_left;
go2_button_state_t top_right;
go2_button_state_t f1;
go2_button_state_t f2;
go2_button_state_t f3;
go2_button_state_t f4;
go2_button_state_t f5;
go2_button_state_t f6;
} go2_gamepad_buttons_t;
typedef struct
{
go2_button_state_t up;
go2_button_state_t down;
go2_button_state_t left;
go2_button_state_t right;
} go2_dpad_t;
typedef struct
{
go2_thumb_t thumb;
go2_dpad_t dpad;
go2_gamepad_buttons_t buttons;
} go2_gamepad_state_t;
typedef struct go2_input go2_input_t;
typedef enum
{
Battery_Status_Unknown = 0,
Battery_Status_Discharging,
Battery_Status_Charging,
Battery_Status_Full,
Battery_Status_MAX = 0x7fffffff
} go2_battery_status_t;
typedef struct
{
uint32_t level;
go2_battery_status_t status;
} go2_battery_state_t;
#ifdef __cplusplus
extern "C" {
#endif
go2_input_t* go2_input_create();
void go2_input_destroy(go2_input_t* input);
void go2_input_gamepad_read(go2_input_t* input, go2_gamepad_state_t* outGamepadState);
void go2_input_battery_read(go2_input_t* input, go2_battery_state_t* outBatteryState);
#ifdef __cplusplus
}
#endif

106
deps/libgo2/src/queue.c vendored Normal file
View File

@ -0,0 +1,106 @@
/*
libgo2 - Support library for the ODROID-GO Advance
Copyright (C) 2020 OtherCrashOverride
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.1 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, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include "queue.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef struct go2_queue
{
int capacity;
int count;
void** data;
} go2_queue_t;
go2_queue_t* go2_queue_create(int capacity)
{
go2_queue_t* result = malloc(sizeof(*result));
if (!result)
{
printf("malloc failed.\n");
return NULL;
}
memset(result, 0, sizeof(*result));
result->capacity = capacity;
result->data = malloc(capacity * sizeof(void*));
if (!result)
{
printf("data malloc failed.\n");
free(result);
return NULL;
}
return result;
}
int go2_queue_count_get(go2_queue_t* queue)
{
return queue->count;
}
void go2_queue_push(go2_queue_t* queue, void* value)
{
if (queue->count < queue->capacity)
{
queue->data[queue->count] = value;
queue->count++;
}
else
{
printf("queue is full.\n");
}
}
void* go2_queue_pop(go2_queue_t* queue)
{
void* result;
if (queue->count > 0)
{
result = queue->data[0];
for (int i = 0; i < queue->count - 1; ++i)
{
queue->data[i] = queue->data[i + 1];
}
queue->count--;
}
else
{
printf("queue is empty.\n");
result = NULL;
}
return result;
}
void go2_queue_destroy(go2_queue_t* queue)
{
free(queue->data);
free(queue);
}

37
deps/libgo2/src/queue.h vendored Normal file
View File

@ -0,0 +1,37 @@
#pragma once
/*
libgo2 - Support library for the ODROID-GO Advance
Copyright (C) 2020 OtherCrashOverride
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.1 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, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
typedef struct go2_queue go2_queue_t;
#ifdef __cplusplus
extern "C" {
#endif
go2_queue_t* go2_queue_create(int capacity);
int go2_queue_count_get(go2_queue_t* queue);
void go2_queue_push(go2_queue_t* queue, void* value);
void* go2_queue_pop(go2_queue_t* queue);
void go2_queue_destroy(go2_queue_t* queue);
#ifdef __cplusplus
}
#endif

View File

@ -43,7 +43,7 @@
#include "../common/drm_common.h"
#ifdef HAVE_ODROIDGO2
#include <rk_rga/RgaApi.h>
#include <go2/display.h>
#include <drm/drm_fourcc.h>
#endif
@ -73,19 +73,27 @@
static enum gfx_ctx_api drm_api = GFX_CTX_NONE;
#ifndef HAVE_ODROIDGO2
static struct gbm_bo *g_bo = NULL;
static struct gbm_bo *g_next_bo = NULL;
static struct gbm_surface *g_gbm_surface = NULL;
static struct gbm_device *g_gbm_dev = NULL;
static bool waiting_for_flip = false;
#endif
typedef struct gfx_ctx_drm_data
{
#ifdef HAVE_EGL
egl_ctx_data_t egl;
#endif
#ifndef HAVE_ODROIDGO2
int fd;
#else
go2_display_t* display;
go2_presenter_t* presenter;
go2_context_t* context;
#endif
int interval;
unsigned fb_width;
unsigned fb_height;
@ -93,6 +101,7 @@ typedef struct gfx_ctx_drm_data
bool core_hw_context_enable;
} gfx_ctx_drm_data_t;
#ifndef HAVE_ODROIDGO2
struct drm_fb
{
struct gbm_bo *bo;
@ -139,26 +148,6 @@ error:
return NULL;
}
static void gfx_ctx_drm_swap_interval(void *data, int interval)
{
gfx_ctx_drm_data_t *drm = (gfx_ctx_drm_data_t*)data;
drm->interval = interval;
if (interval > 1)
RARCH_WARN("[KMS]: Swap intervals > 1 currently not supported. Will use swap interval of 1.\n");
}
static void gfx_ctx_drm_check_window(void *data, bool *quit,
bool *resize, unsigned *width, unsigned *height, bool is_shutdown)
{
(void)data;
(void)width;
(void)height;
*resize = false;
*quit = (bool)frontend_driver_get_signal_handler_state();
}
static void drm_flip_handler(int fd, unsigned frame,
unsigned sec, unsigned usec, void *data)
{
@ -233,7 +222,57 @@ static bool gfx_ctx_drm_queue_flip(void)
/* Failed to queue page flip. */
return false;
}
#endif
static void gfx_ctx_drm_swap_interval(void *data, int interval)
{
gfx_ctx_drm_data_t *drm = (gfx_ctx_drm_data_t*)data;
drm->interval = interval;
if (interval > 1)
RARCH_WARN("[KMS]: Swap intervals > 1 currently not supported. Will use swap interval of 1.\n");
}
static void gfx_ctx_drm_check_window(void *data, bool *quit,
bool *resize, unsigned *width, unsigned *height, bool is_shutdown)
{
(void)data;
(void)width;
(void)height;
*resize = false;
*quit = (bool)frontend_driver_get_signal_handler_state();
}
#ifdef HAVE_ODROIDGO2
static void gfx_ctx_drm_swap_buffers(void *data, void *data2)
{
gfx_ctx_drm_data_t *drm = (gfx_ctx_drm_data_t*)data;
video_frame_info_t *video_info = (video_frame_info_t*)data2;
switch (drm_api)
{
case GFX_CTX_OPENGL_API:
case GFX_CTX_OPENGL_ES_API:
case GFX_CTX_OPENVG_API:
#ifdef HAVE_EGL
go2_context_swap_buffers(drm->context);
go2_surface_t* surface = go2_context_surface_lock(drm->context);
go2_presenter_post(drm->presenter,
surface,
0, 0, 480, 320,
0, 0, 320, 480,
GO2_ROTATION_DEGREES_270);
go2_context_surface_unlock(drm->context, surface);
#endif
break;
default:
printf("unhandled gfx_ctx_drm_swap_buffers\n");
break;
}
}
#else
static void gfx_ctx_drm_swap_buffers(void *data, void *data2)
{
gfx_ctx_drm_data_t *drm = (gfx_ctx_drm_data_t*)data;
@ -270,18 +309,6 @@ static void gfx_ctx_drm_swap_buffers(void *data, void *data2)
gfx_ctx_drm_wait_flip(true);
}
static void gfx_ctx_drm_get_video_size(void *data,
unsigned *width, unsigned *height)
{
gfx_ctx_drm_data_t *drm = (gfx_ctx_drm_data_t*)data;
if (!drm)
return;
*width = drm->fb_width;
*height = drm->fb_height;
}
static void free_drm_resources(gfx_ctx_drm_data_t *drm)
{
if (!drm)
@ -311,7 +338,21 @@ static void free_drm_resources(gfx_ctx_drm_data_t *drm)
g_gbm_dev = NULL;
g_drm_fd = -1;
}
#endif
static void gfx_ctx_drm_get_video_size(void *data,
unsigned *width, unsigned *height)
{
gfx_ctx_drm_data_t *drm = (gfx_ctx_drm_data_t*)data;
if (!drm)
return;
*width = drm->fb_width;
*height = drm->fb_height;
}
#ifndef HAVE_ODROIDGO2
static void gfx_ctx_drm_destroy_resources(gfx_ctx_drm_data_t *drm)
{
if (!drm)
@ -346,19 +387,24 @@ static void gfx_ctx_drm_destroy_resources(gfx_ctx_drm_data_t *drm)
g_bo = NULL;
g_next_bo = NULL;
}
#endif
static void *gfx_ctx_drm_init(video_frame_info_t *video_info, void *video_driver)
{
#ifndef HAVE_ODROIDGO2
int fd, i;
unsigned monitor_index;
unsigned gpu_index = 0;
const char *gpu = NULL;
struct string_list *gpu_descriptors = NULL;
#endif
gfx_ctx_drm_data_t *drm = (gfx_ctx_drm_data_t*)
calloc(1, sizeof(gfx_ctx_drm_data_t));
if (!drm)
return NULL;
#ifndef HAVE_ODROIDGO2
drm->fd = -1;
gpu_descriptors = dir_list_new("/dev/dri", NULL, false, true, false, false);
@ -435,8 +481,14 @@ error:
free(drm);
return NULL;
#else
drm->display = go2_display_create();
drm->presenter = go2_presenter_create(drm->display, DRM_FORMAT_RGB565, 0xff080808);
return drm;
#endif
}
#ifndef HAVE_ODROIDGO2
static EGLint *gfx_ctx_drm_egl_fill_attribs(
gfx_ctx_drm_data_t *drm, EGLint *attr)
{
@ -505,7 +557,9 @@ static EGLint *gfx_ctx_drm_egl_fill_attribs(
*attr = EGL_NONE;
return attr;
}
#endif
#ifndef HAVE_ODROIDGO2
#ifdef HAVE_EGL
static bool gbm_choose_xrgb8888_cb(void *display_data, EGLDisplay dpy, EGLConfig config)
{
@ -528,6 +582,8 @@ static bool gbm_choose_xrgb8888_cb(void *display_data, EGLDisplay dpy, EGLConfig
return id == GBM_FORMAT_XRGB8888;
}
#endif
#endif
#define DRM_EGL_ATTRIBS_BASE \
EGL_SURFACE_TYPE, EGL_WINDOW_BIT, \
@ -537,6 +593,7 @@ static bool gbm_choose_xrgb8888_cb(void *display_data, EGLDisplay dpy, EGLConfig
EGL_ALPHA_SIZE, 0, \
EGL_DEPTH_SIZE, 0
#ifndef HAVE_ODROIDGO2
static bool gfx_ctx_drm_egl_set_video_mode(gfx_ctx_drm_data_t *drm)
{
const EGLint *attrib_ptr = NULL;
@ -644,9 +701,11 @@ static bool gfx_ctx_drm_set_video_mode(void *data,
unsigned width, unsigned height,
bool fullscreen)
{
#ifndef HAVE_ODROIDGO2
float refresh_mod;
int i, ret = 0;
struct drm_fb *fb = NULL;
#endif
gfx_ctx_drm_data_t *drm = (gfx_ctx_drm_data_t*)data;
if (!drm)
@ -654,6 +713,7 @@ static bool gfx_ctx_drm_set_video_mode(void *data,
frontend_driver_install_signal_handler();
#ifndef HAVE_ODROIDGO2
/* If we use black frame insertion,
* we fake a 60 Hz monitor for 120 Hz one,
* etc, so try to match that. */
@ -710,7 +770,13 @@ static bool gfx_ctx_drm_set_video_mode(void *data,
drm->fb_height,
GBM_FORMAT_XRGB8888,
GBM_BO_USE_SCANOUT | GBM_BO_USE_RENDERING);
#else
/* Hardcoded odroidgo2 display resolution */
drm->fb_width = 480;
drm->fb_height = 320;
#endif
#ifndef HAVE_ODROIDGO2
if (!g_gbm_surface)
{
RARCH_ERR("[KMS/EGL]: Couldn't create GBM surface.\n");
@ -753,6 +819,25 @@ error:
free(drm);
return false;
#else
go2_context_attributes_t attr;
attr.major = 3;
attr.minor = 2;
attr.red_bits = 8;
attr.green_bits = 8;
attr.blue_bits = 8;
attr.alpha_bits = 8;
attr.depth_bits = 0;
attr.stencil_bits = 0;
/* Hardcoded odroidgo2 display resolution */
drm->context = go2_context_create(drm->display, 480, 320, &attr);
go2_context_make_current(drm->context);
glClear(GL_COLOR_BUFFER_BIT);
return true;
#endif
}
static void gfx_ctx_drm_destroy(void *data)
@ -762,8 +847,22 @@ static void gfx_ctx_drm_destroy(void *data)
if (!drm)
return;
#ifndef HAVE_ODROIDGO2
gfx_ctx_drm_destroy_resources(drm);
free(drm);
#else
if (drm->context)
{
go2_context_destroy(drm->context);
drm->context = NULL;
}
go2_presenter_destroy(drm->presenter);
drm->presenter = NULL;
go2_display_destroy(drm->display);
drm->display = NULL;
#endif
}
static void gfx_ctx_drm_input_driver(void *data,

View File

@ -637,10 +637,3 @@ fi
check_enabled 'ZLIB BUILTINZLIB' RPNG RPNG 'zlib is' false
check_enabled V4L2 VIDEOPROCESSOR 'video processor' 'Video4linux2 is' true
if [ "$HAVE_ODROIDGO2" != 'no' ]; then
check_pkgconf LIBRGA librk_rga
if [ "$HAVE_LIBRGA" != 'yes' ]; then
die 1 'librga is required for ODROID-GO Advance support'
fi
fi