rosalina: refactor screen filter code
https://i.kym-cdn.com/photos/images/original/001/264/842/220.png
This commit is contained in:
parent
571592ca7c
commit
6592b516a4
@ -46,7 +46,7 @@ CXXFLAGS := $(CFLAGS) -fno-rtti -fno-exceptions -std=gnu++11
|
|||||||
ASFLAGS := -g $(ARCH)
|
ASFLAGS := -g $(ARCH)
|
||||||
LDFLAGS = -specs=3dsx.specs -g $(ARCH) -Wl,-Map,$(notdir $*.map),-wrap,exit,--section-start,.text=0x14000000
|
LDFLAGS = -specs=3dsx.specs -g $(ARCH) -Wl,-Map,$(notdir $*.map),-wrap,exit,--section-start,.text=0x14000000
|
||||||
|
|
||||||
LIBS := -lctru
|
LIBS := -lctru -lm
|
||||||
|
|
||||||
#---------------------------------------------------------------------------------
|
#---------------------------------------------------------------------------------
|
||||||
# list of directories containing libraries, this must be the top level containing
|
# list of directories containing libraries, this must be the top level containing
|
||||||
|
@ -31,6 +31,9 @@
|
|||||||
extern Menu screenFiltersMenu;
|
extern Menu screenFiltersMenu;
|
||||||
|
|
||||||
extern int screenFiltersCurrentTemperature;
|
extern int screenFiltersCurrentTemperature;
|
||||||
|
extern float screenFiltersCurrentGamma;
|
||||||
|
extern float screenFiltersCurrentContrast;
|
||||||
|
extern float screenFiltersCurrentBrightness;
|
||||||
|
|
||||||
void ScreenFiltersMenu_SetCct(int cct);
|
void ScreenFiltersMenu_SetCct(int cct);
|
||||||
void ScreenFiltersMenu_RestoreCct(void);
|
void ScreenFiltersMenu_RestoreCct(void);
|
||||||
|
@ -22,11 +22,8 @@
|
|||||||
|
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
|
||||||
#include "redshift.h"
|
//#include "redshift.h"
|
||||||
|
|
||||||
void colorramp_fill(uint16_t *gamma_r, uint16_t *gamma_g, uint16_t *gamma_b,
|
void colorramp_get_white_point(float *out_white_point, int temperature); // not in original code
|
||||||
int size, const color_setting_t *setting);
|
|
||||||
void colorramp_fill_float(float *gamma_r, float *gamma_g, float *gamma_b,
|
|
||||||
int size, const color_setting_t *setting);
|
|
||||||
|
|
||||||
#endif /* ! REDSHIFT_COLORRAMP_H */
|
#endif /* ! REDSHIFT_COLORRAMP_H */
|
@ -1,153 +0,0 @@
|
|||||||
/* redshift.h -- Main program header
|
|
||||||
This file is part of Redshift.
|
|
||||||
|
|
||||||
Redshift is free software: you can redistribute it and/or modify
|
|
||||||
it under the terms of the GNU General Public License as published by
|
|
||||||
the Free Software Foundation, either version 3 of the License, or
|
|
||||||
(at your option) any later version.
|
|
||||||
|
|
||||||
Redshift 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 General Public License for more details.
|
|
||||||
|
|
||||||
You should have received a copy of the GNU General Public License
|
|
||||||
along with Redshift. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
|
|
||||||
Copyright (c) 2013-2017 Jon Lund Steffensen <jonlst@gmail.com>
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef REDSHIFT_REDSHIFT_H
|
|
||||||
#define REDSHIFT_REDSHIFT_H
|
|
||||||
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
|
|
||||||
/* The color temperature when no adjustment is applied. */
|
|
||||||
#define NEUTRAL_TEMP 6500
|
|
||||||
|
|
||||||
|
|
||||||
/* Location */
|
|
||||||
typedef struct {
|
|
||||||
float lat;
|
|
||||||
float lon;
|
|
||||||
} location_t;
|
|
||||||
|
|
||||||
/* Periods of day. */
|
|
||||||
typedef enum {
|
|
||||||
PERIOD_NONE = 0,
|
|
||||||
PERIOD_DAYTIME,
|
|
||||||
PERIOD_NIGHT,
|
|
||||||
PERIOD_TRANSITION
|
|
||||||
} period_t;
|
|
||||||
|
|
||||||
/* Color setting */
|
|
||||||
typedef struct {
|
|
||||||
int temperature;
|
|
||||||
float gamma[3];
|
|
||||||
float brightness;
|
|
||||||
} color_setting_t;
|
|
||||||
|
|
||||||
/* Program modes. */
|
|
||||||
typedef enum {
|
|
||||||
PROGRAM_MODE_CONTINUAL,
|
|
||||||
PROGRAM_MODE_ONE_SHOT,
|
|
||||||
PROGRAM_MODE_PRINT,
|
|
||||||
PROGRAM_MODE_RESET,
|
|
||||||
PROGRAM_MODE_MANUAL
|
|
||||||
} program_mode_t;
|
|
||||||
|
|
||||||
/* Time range.
|
|
||||||
Fields are offsets from midnight in seconds. */
|
|
||||||
typedef struct {
|
|
||||||
int start;
|
|
||||||
int end;
|
|
||||||
} time_range_t;
|
|
||||||
|
|
||||||
/* Transition scheme.
|
|
||||||
The solar elevations at which the transition begins/ends,
|
|
||||||
and the association color settings. */
|
|
||||||
typedef struct {
|
|
||||||
double high;
|
|
||||||
double low;
|
|
||||||
int use_time; /* When enabled, ignore elevation and use time ranges. */
|
|
||||||
time_range_t dawn;
|
|
||||||
time_range_t dusk;
|
|
||||||
color_setting_t day;
|
|
||||||
color_setting_t night;
|
|
||||||
} transition_scheme_t;
|
|
||||||
|
|
||||||
|
|
||||||
/* Gamma adjustment method */
|
|
||||||
typedef struct gamma_state gamma_state_t;
|
|
||||||
|
|
||||||
typedef int gamma_method_init_func(gamma_state_t **state);
|
|
||||||
typedef int gamma_method_start_func(gamma_state_t *state);
|
|
||||||
typedef void gamma_method_free_func(gamma_state_t *state);
|
|
||||||
typedef void gamma_method_print_help_func(FILE *f);
|
|
||||||
typedef int gamma_method_set_option_func(gamma_state_t *state, const char *key,
|
|
||||||
const char *value);
|
|
||||||
typedef void gamma_method_restore_func(gamma_state_t *state);
|
|
||||||
typedef int gamma_method_set_temperature_func(
|
|
||||||
gamma_state_t *state, const color_setting_t *setting, int preserve);
|
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
char *name;
|
|
||||||
|
|
||||||
/* If true, this method will be tried if none is explicitly chosen. */
|
|
||||||
int autostart;
|
|
||||||
|
|
||||||
/* Initialize state. Options can be set between init and start. */
|
|
||||||
gamma_method_init_func *init;
|
|
||||||
/* Allocate storage and make connections that depend on options. */
|
|
||||||
gamma_method_start_func *start;
|
|
||||||
/* Free all allocated storage and close connections. */
|
|
||||||
gamma_method_free_func *free;
|
|
||||||
|
|
||||||
/* Print help on options for this adjustment method. */
|
|
||||||
gamma_method_print_help_func *print_help;
|
|
||||||
/* Set an option key, value-pair */
|
|
||||||
gamma_method_set_option_func *set_option;
|
|
||||||
|
|
||||||
/* Restore the adjustment to the state before start was called. */
|
|
||||||
gamma_method_restore_func *restore;
|
|
||||||
/* Set a specific color temperature. */
|
|
||||||
gamma_method_set_temperature_func *set_temperature;
|
|
||||||
} gamma_method_t;
|
|
||||||
|
|
||||||
|
|
||||||
/* Location provider */
|
|
||||||
typedef struct location_state location_state_t;
|
|
||||||
|
|
||||||
typedef int location_provider_init_func(location_state_t **state);
|
|
||||||
typedef int location_provider_start_func(location_state_t *state);
|
|
||||||
typedef void location_provider_free_func(location_state_t *state);
|
|
||||||
typedef void location_provider_print_help_func(FILE *f);
|
|
||||||
typedef int location_provider_set_option_func(
|
|
||||||
location_state_t *state, const char *key, const char *value);
|
|
||||||
typedef int location_provider_get_fd_func(location_state_t *state);
|
|
||||||
typedef int location_provider_handle_func(
|
|
||||||
location_state_t *state, location_t *location, int *available);
|
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
char *name;
|
|
||||||
|
|
||||||
/* Initialize state. Options can be set between init and start. */
|
|
||||||
location_provider_init_func *init;
|
|
||||||
/* Allocate storage and make connections that depend on options. */
|
|
||||||
location_provider_start_func *start;
|
|
||||||
/* Free all allocated storage and close connections. */
|
|
||||||
location_provider_free_func *free;
|
|
||||||
|
|
||||||
/* Print help on options for this location provider. */
|
|
||||||
location_provider_print_help_func *print_help;
|
|
||||||
/* Set an option key, value-pair. */
|
|
||||||
location_provider_set_option_func *set_option;
|
|
||||||
|
|
||||||
/* Listen and handle location updates. */
|
|
||||||
location_provider_get_fd_func *get_fd;
|
|
||||||
location_provider_handle_func *handle;
|
|
||||||
} location_provider_t;
|
|
||||||
|
|
||||||
|
|
||||||
#endif /* ! REDSHIFT_REDSHIFT_H */
|
|
@ -25,11 +25,11 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include <3ds.h>
|
#include <3ds.h>
|
||||||
|
#include <math.h>
|
||||||
#include "memory.h"
|
#include "memory.h"
|
||||||
#include "menu.h"
|
#include "menu.h"
|
||||||
#include "menus/screen_filters.h"
|
#include "menus/screen_filters.h"
|
||||||
#include "draw.h"
|
#include "draw.h"
|
||||||
#include "redshift/redshift.h"
|
|
||||||
#include "redshift/colorramp.h"
|
#include "redshift/colorramp.h"
|
||||||
|
|
||||||
typedef union {
|
typedef union {
|
||||||
@ -42,67 +42,54 @@ typedef union {
|
|||||||
u32 raw;
|
u32 raw;
|
||||||
} Pixel;
|
} Pixel;
|
||||||
|
|
||||||
static u16 g_c[0x600];
|
|
||||||
static Pixel g_px[0x400];
|
|
||||||
|
|
||||||
int screenFiltersCurrentTemperature = 6500;
|
int screenFiltersCurrentTemperature = 6500;
|
||||||
|
float screenFiltersCurrentGamma = 1.0f;
|
||||||
|
float screenFiltersCurrentContrast = 1.0f;
|
||||||
|
float screenFiltersCurrentBrightness = 0.0f;
|
||||||
|
|
||||||
static void ScreenFiltersMenu_WriteLut(const Pixel* lut)
|
static inline bool ScreenFiltersMenu_IsDefaultSettings(void)
|
||||||
|
{
|
||||||
|
bool ret = screenFiltersCurrentTemperature == 6500;
|
||||||
|
ret = ret && screenFiltersCurrentGamma == 1.0f;
|
||||||
|
ret = ret && screenFiltersCurrentContrast == 1.0f;
|
||||||
|
ret = ret && screenFiltersCurrentBrightness == 0.0f;
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline u8 ScreenFiltersMenu_GetColorLevel(int inLevel, float wp, float a, float b, float g)
|
||||||
|
{
|
||||||
|
float level = inLevel / 255.0f;
|
||||||
|
level = powf(a * wp * level + b, g);
|
||||||
|
s32 levelInt = (s32)(255.0f * level + 0.5f); // round to nearest integer
|
||||||
|
return levelInt <= 0 ? 0 : levelInt >= 255 ? 255 : (u8)levelInt; // clamp
|
||||||
|
}
|
||||||
|
|
||||||
|
static void ScreenFiltersMenu_ApplyColorSettings(void)
|
||||||
{
|
{
|
||||||
GPU_FB_TOP_COL_LUT_INDEX = 0;
|
GPU_FB_TOP_COL_LUT_INDEX = 0;
|
||||||
GPU_FB_BOTTOM_COL_LUT_INDEX = 0;
|
GPU_FB_BOTTOM_COL_LUT_INDEX = 0;
|
||||||
|
|
||||||
|
float wp[3];
|
||||||
|
colorramp_get_white_point(wp, screenFiltersCurrentTemperature);
|
||||||
|
float a = screenFiltersCurrentContrast;
|
||||||
|
float g = screenFiltersCurrentGamma;
|
||||||
|
float b = screenFiltersCurrentBrightness;
|
||||||
|
|
||||||
for (int i = 0; i <= 255; i++) {
|
for (int i = 0; i <= 255; i++) {
|
||||||
GPU_FB_TOP_COL_LUT_ELEM = lut->raw;
|
Pixel px;
|
||||||
GPU_FB_BOTTOM_COL_LUT_ELEM = lut->raw;
|
px.r = ScreenFiltersMenu_GetColorLevel(i, wp[0], a, b, g);
|
||||||
lut++;
|
px.g = ScreenFiltersMenu_GetColorLevel(i, wp[1], a, b, g);
|
||||||
|
px.b = ScreenFiltersMenu_GetColorLevel(i, wp[2], a, b, g);
|
||||||
|
px.z = 0;
|
||||||
|
GPU_FB_TOP_COL_LUT_ELEM = px.raw;
|
||||||
|
GPU_FB_BOTTOM_COL_LUT_ELEM = px.raw;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void ScreenFiltersMenu_ApplyColorSettings(color_setting_t* cs)
|
|
||||||
{
|
|
||||||
u8 i = 0;
|
|
||||||
|
|
||||||
memset(g_c, 0, sizeof(g_c));
|
|
||||||
memset(g_px, 0, sizeof(g_px));
|
|
||||||
|
|
||||||
do {
|
|
||||||
g_px[i].r = i;
|
|
||||||
g_px[i].g = i;
|
|
||||||
g_px[i].b = i;
|
|
||||||
g_px[i].z = 0;
|
|
||||||
} while(++i);
|
|
||||||
|
|
||||||
do {
|
|
||||||
*(g_c + i + 0x000) = g_px[i].r | (g_px[i].r << 8);
|
|
||||||
*(g_c + i + 0x100) = g_px[i].g | (g_px[i].g << 8);
|
|
||||||
*(g_c + i + 0x200) = g_px[i].b | (g_px[i].b << 8);
|
|
||||||
} while(++i);
|
|
||||||
|
|
||||||
colorramp_fill(g_c + 0x000, g_c + 0x100, g_c + 0x200, 0x100, cs);
|
|
||||||
|
|
||||||
do {
|
|
||||||
g_px[i].r = *(g_c + i + 0x000) >> 8;
|
|
||||||
g_px[i].g = *(g_c + i + 0x100) >> 8;
|
|
||||||
g_px[i].b = *(g_c + i + 0x200) >> 8;
|
|
||||||
} while(++i);
|
|
||||||
|
|
||||||
ScreenFiltersMenu_WriteLut(g_px);
|
|
||||||
}
|
|
||||||
|
|
||||||
void ScreenFiltersMenu_SetCct(int cct)
|
void ScreenFiltersMenu_SetCct(int cct)
|
||||||
{
|
{
|
||||||
color_setting_t cs;
|
|
||||||
memset(&cs, 0, sizeof(cs));
|
|
||||||
|
|
||||||
cs.temperature = cct;
|
|
||||||
/*cs.gamma[0] = 1.0F;
|
|
||||||
cs.gamma[1] = 1.0F;
|
|
||||||
cs.gamma[2] = 1.0F;
|
|
||||||
cs.brightness = 1.0F;*/
|
|
||||||
|
|
||||||
ScreenFiltersMenu_ApplyColorSettings(&cs);
|
|
||||||
screenFiltersCurrentTemperature = cct;
|
screenFiltersCurrentTemperature = cct;
|
||||||
|
ScreenFiltersMenu_ApplyColorSettings();
|
||||||
}
|
}
|
||||||
|
|
||||||
Menu screenFiltersMenu = {
|
Menu screenFiltersMenu = {
|
||||||
@ -131,15 +118,12 @@ void ScreenFiltersMenu_Set##name(void)\
|
|||||||
void ScreenFiltersMenu_RestoreCct(void)
|
void ScreenFiltersMenu_RestoreCct(void)
|
||||||
{
|
{
|
||||||
// Not initialized/default: return
|
// Not initialized/default: return
|
||||||
if (screenFiltersCurrentTemperature == 6500)
|
if (ScreenFiltersMenu_IsDefaultSettings())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
// Wait for GSP to restore the CCT table
|
// Wait for GSP to restore the CCT table
|
||||||
while (GPU_FB_TOP_COL_LUT_ELEM != g_px[0].raw)
|
svcSleepThread(20 * 1000 * 1000LL);
|
||||||
svcSleepThread(10 * 1000 * 1000LL);
|
ScreenFiltersMenu_ApplyColorSettings();
|
||||||
|
|
||||||
svcSleepThread(10 * 1000 * 1000LL);
|
|
||||||
ScreenFiltersMenu_WriteLut(g_px);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
DEF_CCT_SETTER(6500, Default)
|
DEF_CCT_SETTER(6500, Default)
|
||||||
|
@ -21,7 +21,7 @@
|
|||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
//#include <math.h>
|
//#include <math.h>
|
||||||
|
|
||||||
#include "redshift/redshift.h"
|
//#include "redshift/redshift.h"
|
||||||
|
|
||||||
/* Whitepoint values for temperatures at 100K intervals.
|
/* Whitepoint values for temperatures at 100K intervals.
|
||||||
These will be interpolated for the actual temperature.
|
These will be interpolated for the actual temperature.
|
||||||
@ -281,49 +281,13 @@ interpolate_color(float a, const float *c1, const float *c2, float *c)
|
|||||||
c[2] = (1.0-a)*c1[2] + a*c2[2];
|
c[2] = (1.0-a)*c1[2] + a*c2[2];
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Helper macro used in the fill functions */
|
|
||||||
#define F(Y, C) ((Y) * white_point[C])
|
|
||||||
|
|
||||||
/*#define F(Y, C) pow((Y) * setting->brightness * \
|
// Not in original code
|
||||||
white_point[C], 1.0/setting->gamma[C])*/
|
void colorramp_get_white_point(float *out_white_point, int temperature)
|
||||||
|
|
||||||
void
|
|
||||||
colorramp_fill(uint16_t *gamma_r, uint16_t *gamma_g, uint16_t *gamma_b,
|
|
||||||
int size, const color_setting_t *setting)
|
|
||||||
{
|
{
|
||||||
/* Approximate white point */
|
/* Approximate white point */
|
||||||
float white_point[3];
|
float alpha = (temperature % 100) / 100.0;
|
||||||
float alpha = (setting->temperature % 100) / 100.0;
|
int temp_index = ((temperature - 1000) / 100)*3;
|
||||||
int temp_index = ((setting->temperature - 1000) / 100)*3;
|
|
||||||
interpolate_color(alpha, &blackbody_color[temp_index],
|
interpolate_color(alpha, &blackbody_color[temp_index],
|
||||||
&blackbody_color[temp_index+3], white_point);
|
&blackbody_color[temp_index+3], out_white_point);
|
||||||
|
|
||||||
for (int i = 0; i < size; i++) {
|
|
||||||
gamma_r[i] = F((double)gamma_r[i]/(UINT16_MAX+1), 0) *
|
|
||||||
(UINT16_MAX+1);
|
|
||||||
gamma_g[i] = F((double)gamma_g[i]/(UINT16_MAX+1), 1) *
|
|
||||||
(UINT16_MAX+1);
|
|
||||||
gamma_b[i] = F((double)gamma_b[i]/(UINT16_MAX+1), 2) *
|
|
||||||
(UINT16_MAX+1);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
|
||||||
colorramp_fill_float(float *gamma_r, float *gamma_g, float *gamma_b,
|
|
||||||
int size, const color_setting_t *setting)
|
|
||||||
{
|
|
||||||
/* Approximate white point */
|
|
||||||
float white_point[3];
|
|
||||||
float alpha = (setting->temperature % 100) / 100.0;
|
|
||||||
int temp_index = ((setting->temperature - 1000) / 100)*3;
|
|
||||||
interpolate_color(alpha, &blackbody_color[temp_index],
|
|
||||||
&blackbody_color[temp_index+3], white_point);
|
|
||||||
|
|
||||||
for (int i = 0; i < size; i++) {
|
|
||||||
gamma_r[i] = F((double)gamma_r[i], 0);
|
|
||||||
gamma_g[i] = F((double)gamma_g[i], 1);
|
|
||||||
gamma_b[i] = F((double)gamma_b[i], 2);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#undef F
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user