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)
|
||||
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
|
||||
|
@ -31,6 +31,9 @@
|
||||
extern Menu screenFiltersMenu;
|
||||
|
||||
extern int screenFiltersCurrentTemperature;
|
||||
extern float screenFiltersCurrentGamma;
|
||||
extern float screenFiltersCurrentContrast;
|
||||
extern float screenFiltersCurrentBrightness;
|
||||
|
||||
void ScreenFiltersMenu_SetCct(int cct);
|
||||
void ScreenFiltersMenu_RestoreCct(void);
|
||||
|
@ -22,11 +22,8 @@
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#include "redshift.h"
|
||||
//#include "redshift.h"
|
||||
|
||||
void colorramp_fill(uint16_t *gamma_r, uint16_t *gamma_g, uint16_t *gamma_b,
|
||||
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);
|
||||
void colorramp_get_white_point(float *out_white_point, int temperature); // not in original code
|
||||
|
||||
#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 <math.h>
|
||||
#include "memory.h"
|
||||
#include "menu.h"
|
||||
#include "menus/screen_filters.h"
|
||||
#include "draw.h"
|
||||
#include "redshift/redshift.h"
|
||||
#include "redshift/colorramp.h"
|
||||
|
||||
typedef union {
|
||||
@ -42,67 +42,54 @@ typedef union {
|
||||
u32 raw;
|
||||
} Pixel;
|
||||
|
||||
static u16 g_c[0x600];
|
||||
static Pixel g_px[0x400];
|
||||
|
||||
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_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++) {
|
||||
GPU_FB_TOP_COL_LUT_ELEM = lut->raw;
|
||||
GPU_FB_BOTTOM_COL_LUT_ELEM = lut->raw;
|
||||
lut++;
|
||||
Pixel px;
|
||||
px.r = ScreenFiltersMenu_GetColorLevel(i, wp[0], a, b, g);
|
||||
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)
|
||||
{
|
||||
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;
|
||||
ScreenFiltersMenu_ApplyColorSettings();
|
||||
}
|
||||
|
||||
Menu screenFiltersMenu = {
|
||||
@ -131,15 +118,12 @@ void ScreenFiltersMenu_Set##name(void)\
|
||||
void ScreenFiltersMenu_RestoreCct(void)
|
||||
{
|
||||
// Not initialized/default: return
|
||||
if (screenFiltersCurrentTemperature == 6500)
|
||||
if (ScreenFiltersMenu_IsDefaultSettings())
|
||||
return;
|
||||
|
||||
// Wait for GSP to restore the CCT table
|
||||
while (GPU_FB_TOP_COL_LUT_ELEM != g_px[0].raw)
|
||||
svcSleepThread(10 * 1000 * 1000LL);
|
||||
|
||||
svcSleepThread(10 * 1000 * 1000LL);
|
||||
ScreenFiltersMenu_WriteLut(g_px);
|
||||
svcSleepThread(20 * 1000 * 1000LL);
|
||||
ScreenFiltersMenu_ApplyColorSettings();
|
||||
}
|
||||
|
||||
DEF_CCT_SETTER(6500, Default)
|
||||
|
@ -21,7 +21,7 @@
|
||||
#include <stdint.h>
|
||||
//#include <math.h>
|
||||
|
||||
#include "redshift/redshift.h"
|
||||
//#include "redshift/redshift.h"
|
||||
|
||||
/* Whitepoint values for temperatures at 100K intervals.
|
||||
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];
|
||||
}
|
||||
|
||||
/* Helper macro used in the fill functions */
|
||||
#define F(Y, C) ((Y) * white_point[C])
|
||||
|
||||
/*#define F(Y, C) pow((Y) * setting->brightness * \
|
||||
white_point[C], 1.0/setting->gamma[C])*/
|
||||
|
||||
void
|
||||
colorramp_fill(uint16_t *gamma_r, uint16_t *gamma_g, uint16_t *gamma_b,
|
||||
int size, const color_setting_t *setting)
|
||||
// Not in original code
|
||||
void colorramp_get_white_point(float *out_white_point, int temperature)
|
||||
{
|
||||
/* Approximate white point */
|
||||
float white_point[3];
|
||||
float alpha = (setting->temperature % 100) / 100.0;
|
||||
int temp_index = ((setting->temperature - 1000) / 100)*3;
|
||||
float alpha = (temperature % 100) / 100.0;
|
||||
int temp_index = ((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]/(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);
|
||||
}
|
||||
&blackbody_color[temp_index+3], out_white_point);
|
||||
}
|
||||
|
||||
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