From 7ffb481e2722a2dd43cbc05c72af288be2a7e9c3 Mon Sep 17 00:00:00 2001 From: panicbit Date: Sun, 15 Apr 2018 03:11:18 +0200 Subject: [PATCH 1/7] Add gpu color LUT registers to rosalina --- sysmodules/rosalina/include/draw.h | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/sysmodules/rosalina/include/draw.h b/sysmodules/rosalina/include/draw.h index 3ae019828..6e48c8529 100644 --- a/sysmodules/rosalina/include/draw.h +++ b/sysmodules/rosalina/include/draw.h @@ -34,6 +34,8 @@ #define GPU_FB_TOP_LEFT_ADDR_2 REG32(0x1040046C) #define GPU_FB_TOP_FMT REG32(0x10400470) #define GPU_FB_TOP_SEL REG32(0x10400478) +#define GPU_FB_TOP_COL_LUT_INDEX REG32(0x10400480) +#define GPU_FB_TOP_COL_LUT_ELEM REG32(0x10400484) #define GPU_FB_TOP_STRIDE REG32(0x10400490) #define GPU_FB_TOP_RIGHT_ADDR_1 REG32(0x10400494) #define GPU_FB_TOP_RIGHT_ADDR_2 REG32(0x10400498) @@ -42,6 +44,8 @@ #define GPU_FB_BOTTOM_ADDR_2 REG32(0x1040056C) #define GPU_FB_BOTTOM_FMT REG32(0x10400570) #define GPU_FB_BOTTOM_SEL REG32(0x10400578) +#define GPU_FB_BOTTOM_COL_LUT_INDEX REG32(0x10400580) +#define GPU_FB_BOTTOM_COL_LUT_ELEM REG32(0x10400584) #define GPU_FB_BOTTOM_STRIDE REG32(0x10400590) #define GPU_PSC0_CNT REG32(0x1040001C) From 9f61049dc510b8faafed4e3f5abf517c78c6cdfd Mon Sep 17 00:00:00 2001 From: panicbit Date: Sun, 15 Apr 2018 04:51:09 +0200 Subject: [PATCH 2/7] Add parts of redshift to rosalina --- sysmodules/rosalina/Makefile | 2 +- .../rosalina/include/redshift/colorramp.h | 32 ++ .../rosalina/include/redshift/redshift.h | 153 ++++++++ .../rosalina/source/redshift/colorramp.c | 327 ++++++++++++++++++ 4 files changed, 513 insertions(+), 1 deletion(-) create mode 100644 sysmodules/rosalina/include/redshift/colorramp.h create mode 100644 sysmodules/rosalina/include/redshift/redshift.h create mode 100644 sysmodules/rosalina/source/redshift/colorramp.c diff --git a/sysmodules/rosalina/Makefile b/sysmodules/rosalina/Makefile index 24656de1d..af46716c1 100644 --- a/sysmodules/rosalina/Makefile +++ b/sysmodules/rosalina/Makefile @@ -13,7 +13,7 @@ dir_include := include dir_build := build dir_out := ../../$(dir_build) -LIBS := -lctru +LIBS := -lctru -lm LIBDIRS := $(CTRULIB) LIBPATHS := $(foreach dir,$(LIBDIRS),-L$(dir)/lib) diff --git a/sysmodules/rosalina/include/redshift/colorramp.h b/sysmodules/rosalina/include/redshift/colorramp.h new file mode 100644 index 000000000..985e7749b --- /dev/null +++ b/sysmodules/rosalina/include/redshift/colorramp.h @@ -0,0 +1,32 @@ +/* colorramp.h -- color temperature calculation 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 . + + Copyright (c) 2010-2014 Jon Lund Steffensen +*/ + +#ifndef REDSHIFT_COLORRAMP_H +#define REDSHIFT_COLORRAMP_H + +#include + +#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); + +#endif /* ! REDSHIFT_COLORRAMP_H */ \ No newline at end of file diff --git a/sysmodules/rosalina/include/redshift/redshift.h b/sysmodules/rosalina/include/redshift/redshift.h new file mode 100644 index 000000000..6aca3e6d9 --- /dev/null +++ b/sysmodules/rosalina/include/redshift/redshift.h @@ -0,0 +1,153 @@ +/* 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 . + + Copyright (c) 2013-2017 Jon Lund Steffensen +*/ + +#ifndef REDSHIFT_REDSHIFT_H +#define REDSHIFT_REDSHIFT_H + +#include +#include + +/* 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 */ \ No newline at end of file diff --git a/sysmodules/rosalina/source/redshift/colorramp.c b/sysmodules/rosalina/source/redshift/colorramp.c new file mode 100644 index 000000000..6d647a961 --- /dev/null +++ b/sysmodules/rosalina/source/redshift/colorramp.c @@ -0,0 +1,327 @@ +/* colorramp.c -- color temperature calculation source + 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 . + + Copyright (c) 2013-2014 Jon Lund Steffensen + Copyright (c) 2013 Ingo Thies +*/ + +#include +#include + +#include "redshift/redshift.h" + +/* Whitepoint values for temperatures at 100K intervals. + These will be interpolated for the actual temperature. + This table was provided by Ingo Thies, 2013. See + the file README-colorramp for more information. */ +static const float blackbody_color[] = { + 1.00000000, 0.18172716, 0.00000000, /* 1000K */ + 1.00000000, 0.25503671, 0.00000000, /* 1100K */ + 1.00000000, 0.30942099, 0.00000000, /* 1200K */ + 1.00000000, 0.35357379, 0.00000000, /* ... */ + 1.00000000, 0.39091524, 0.00000000, + 1.00000000, 0.42322816, 0.00000000, + 1.00000000, 0.45159884, 0.00000000, + 1.00000000, 0.47675916, 0.00000000, + 1.00000000, 0.49923747, 0.00000000, + 1.00000000, 0.51943421, 0.00000000, + 1.00000000, 0.54360078, 0.08679949, + 1.00000000, 0.56618736, 0.14065513, + 1.00000000, 0.58734976, 0.18362641, + 1.00000000, 0.60724493, 0.22137978, + 1.00000000, 0.62600248, 0.25591950, + 1.00000000, 0.64373109, 0.28819679, + 1.00000000, 0.66052319, 0.31873863, + 1.00000000, 0.67645822, 0.34786758, + 1.00000000, 0.69160518, 0.37579588, + 1.00000000, 0.70602449, 0.40267128, + 1.00000000, 0.71976951, 0.42860152, + 1.00000000, 0.73288760, 0.45366838, + 1.00000000, 0.74542112, 0.47793608, + 1.00000000, 0.75740814, 0.50145662, + 1.00000000, 0.76888303, 0.52427322, + 1.00000000, 0.77987699, 0.54642268, + 1.00000000, 0.79041843, 0.56793692, + 1.00000000, 0.80053332, 0.58884417, + 1.00000000, 0.81024551, 0.60916971, + 1.00000000, 0.81957693, 0.62893653, + 1.00000000, 0.82854786, 0.64816570, + 1.00000000, 0.83717703, 0.66687674, + 1.00000000, 0.84548188, 0.68508786, + 1.00000000, 0.85347859, 0.70281616, + 1.00000000, 0.86118227, 0.72007777, + 1.00000000, 0.86860704, 0.73688797, + 1.00000000, 0.87576611, 0.75326132, + 1.00000000, 0.88267187, 0.76921169, + 1.00000000, 0.88933596, 0.78475236, + 1.00000000, 0.89576933, 0.79989606, + 1.00000000, 0.90198230, 0.81465502, + 1.00000000, 0.90963069, 0.82838210, + 1.00000000, 0.91710889, 0.84190889, + 1.00000000, 0.92441842, 0.85523742, + 1.00000000, 0.93156127, 0.86836903, + 1.00000000, 0.93853986, 0.88130458, + 1.00000000, 0.94535695, 0.89404470, + 1.00000000, 0.95201559, 0.90658983, + 1.00000000, 0.95851906, 0.91894041, + 1.00000000, 0.96487079, 0.93109690, + 1.00000000, 0.97107439, 0.94305985, + 1.00000000, 0.97713351, 0.95482993, + 1.00000000, 0.98305189, 0.96640795, + 1.00000000, 0.98883326, 0.97779486, + 1.00000000, 0.99448139, 0.98899179, + 1.00000000, 1.00000000, 1.00000000, /* 6500K */ + 0.98947904, 0.99348723, 1.00000000, + 0.97940448, 0.98722715, 1.00000000, + 0.96975025, 0.98120637, 1.00000000, + 0.96049223, 0.97541240, 1.00000000, + 0.95160805, 0.96983355, 1.00000000, + 0.94303638, 0.96443333, 1.00000000, + 0.93480451, 0.95923080, 1.00000000, + 0.92689056, 0.95421394, 1.00000000, + 0.91927697, 0.94937330, 1.00000000, + 0.91194747, 0.94470005, 1.00000000, + 0.90488690, 0.94018594, 1.00000000, + 0.89808115, 0.93582323, 1.00000000, + 0.89151710, 0.93160469, 1.00000000, + 0.88518247, 0.92752354, 1.00000000, + 0.87906581, 0.92357340, 1.00000000, + 0.87315640, 0.91974827, 1.00000000, + 0.86744421, 0.91604254, 1.00000000, + 0.86191983, 0.91245088, 1.00000000, + 0.85657444, 0.90896831, 1.00000000, + 0.85139976, 0.90559011, 1.00000000, + 0.84638799, 0.90231183, 1.00000000, + 0.84153180, 0.89912926, 1.00000000, + 0.83682430, 0.89603843, 1.00000000, + 0.83225897, 0.89303558, 1.00000000, + 0.82782969, 0.89011714, 1.00000000, + 0.82353066, 0.88727974, 1.00000000, + 0.81935641, 0.88452017, 1.00000000, + 0.81530175, 0.88183541, 1.00000000, + 0.81136180, 0.87922257, 1.00000000, + 0.80753191, 0.87667891, 1.00000000, + 0.80380769, 0.87420182, 1.00000000, + 0.80018497, 0.87178882, 1.00000000, + 0.79665980, 0.86943756, 1.00000000, + 0.79322843, 0.86714579, 1.00000000, + 0.78988728, 0.86491137, 1.00000000, /* 10000K */ + 0.78663296, 0.86273225, 1.00000000, + 0.78346225, 0.86060650, 1.00000000, + 0.78037207, 0.85853224, 1.00000000, + 0.77735950, 0.85650771, 1.00000000, + 0.77442176, 0.85453121, 1.00000000, + 0.77155617, 0.85260112, 1.00000000, + 0.76876022, 0.85071588, 1.00000000, + 0.76603147, 0.84887402, 1.00000000, + 0.76336762, 0.84707411, 1.00000000, + 0.76076645, 0.84531479, 1.00000000, + 0.75822586, 0.84359476, 1.00000000, + 0.75574383, 0.84191277, 1.00000000, + 0.75331843, 0.84026762, 1.00000000, + 0.75094780, 0.83865816, 1.00000000, + 0.74863017, 0.83708329, 1.00000000, + 0.74636386, 0.83554194, 1.00000000, + 0.74414722, 0.83403311, 1.00000000, + 0.74197871, 0.83255582, 1.00000000, + 0.73985682, 0.83110912, 1.00000000, + 0.73778012, 0.82969211, 1.00000000, + 0.73574723, 0.82830393, 1.00000000, + 0.73375683, 0.82694373, 1.00000000, + 0.73180765, 0.82561071, 1.00000000, + 0.72989845, 0.82430410, 1.00000000, + 0.72802807, 0.82302316, 1.00000000, + 0.72619537, 0.82176715, 1.00000000, + 0.72439927, 0.82053539, 1.00000000, + 0.72263872, 0.81932722, 1.00000000, + 0.72091270, 0.81814197, 1.00000000, + 0.71922025, 0.81697905, 1.00000000, + 0.71756043, 0.81583783, 1.00000000, + 0.71593234, 0.81471775, 1.00000000, + 0.71433510, 0.81361825, 1.00000000, + 0.71276788, 0.81253878, 1.00000000, + 0.71122987, 0.81147883, 1.00000000, + 0.70972029, 0.81043789, 1.00000000, + 0.70823838, 0.80941546, 1.00000000, + 0.70678342, 0.80841109, 1.00000000, + 0.70535469, 0.80742432, 1.00000000, + 0.70395153, 0.80645469, 1.00000000, + 0.70257327, 0.80550180, 1.00000000, + 0.70121928, 0.80456522, 1.00000000, + 0.69988894, 0.80364455, 1.00000000, + 0.69858167, 0.80273941, 1.00000000, + 0.69729688, 0.80184943, 1.00000000, + 0.69603402, 0.80097423, 1.00000000, + 0.69479255, 0.80011347, 1.00000000, + 0.69357196, 0.79926681, 1.00000000, + 0.69237173, 0.79843391, 1.00000000, + 0.69119138, 0.79761446, 1.00000000, /* 15000K */ + 0.69003044, 0.79680814, 1.00000000, + 0.68888844, 0.79601466, 1.00000000, + 0.68776494, 0.79523371, 1.00000000, + 0.68665951, 0.79446502, 1.00000000, + 0.68557173, 0.79370830, 1.00000000, + 0.68450119, 0.79296330, 1.00000000, + 0.68344751, 0.79222975, 1.00000000, + 0.68241029, 0.79150740, 1.00000000, + 0.68138918, 0.79079600, 1.00000000, + 0.68038380, 0.79009531, 1.00000000, + 0.67939381, 0.78940511, 1.00000000, + 0.67841888, 0.78872517, 1.00000000, + 0.67745866, 0.78805526, 1.00000000, + 0.67651284, 0.78739518, 1.00000000, + 0.67558112, 0.78674472, 1.00000000, + 0.67466317, 0.78610368, 1.00000000, + 0.67375872, 0.78547186, 1.00000000, + 0.67286748, 0.78484907, 1.00000000, + 0.67198916, 0.78423512, 1.00000000, + 0.67112350, 0.78362984, 1.00000000, + 0.67027024, 0.78303305, 1.00000000, + 0.66942911, 0.78244457, 1.00000000, + 0.66859988, 0.78186425, 1.00000000, + 0.66778228, 0.78129191, 1.00000000, + 0.66697610, 0.78072740, 1.00000000, + 0.66618110, 0.78017057, 1.00000000, + 0.66539706, 0.77962127, 1.00000000, + 0.66462376, 0.77907934, 1.00000000, + 0.66386098, 0.77854465, 1.00000000, + 0.66310852, 0.77801705, 1.00000000, + 0.66236618, 0.77749642, 1.00000000, + 0.66163375, 0.77698261, 1.00000000, + 0.66091106, 0.77647551, 1.00000000, + 0.66019791, 0.77597498, 1.00000000, + 0.65949412, 0.77548090, 1.00000000, + 0.65879952, 0.77499315, 1.00000000, + 0.65811392, 0.77451161, 1.00000000, + 0.65743716, 0.77403618, 1.00000000, + 0.65676908, 0.77356673, 1.00000000, + 0.65610952, 0.77310316, 1.00000000, + 0.65545831, 0.77264537, 1.00000000, + 0.65481530, 0.77219324, 1.00000000, + 0.65418036, 0.77174669, 1.00000000, + 0.65355332, 0.77130560, 1.00000000, + 0.65293404, 0.77086988, 1.00000000, + 0.65232240, 0.77043944, 1.00000000, + 0.65171824, 0.77001419, 1.00000000, + 0.65112144, 0.76959404, 1.00000000, + 0.65053187, 0.76917889, 1.00000000, + 0.64994941, 0.76876866, 1.00000000, /* 20000K */ + 0.64937392, 0.76836326, 1.00000000, + 0.64880528, 0.76796263, 1.00000000, + 0.64824339, 0.76756666, 1.00000000, + 0.64768812, 0.76717529, 1.00000000, + 0.64713935, 0.76678844, 1.00000000, + 0.64659699, 0.76640603, 1.00000000, + 0.64606092, 0.76602798, 1.00000000, + 0.64553103, 0.76565424, 1.00000000, + 0.64500722, 0.76528472, 1.00000000, + 0.64448939, 0.76491935, 1.00000000, + 0.64397745, 0.76455808, 1.00000000, + 0.64347129, 0.76420082, 1.00000000, + 0.64297081, 0.76384753, 1.00000000, + 0.64247594, 0.76349813, 1.00000000, + 0.64198657, 0.76315256, 1.00000000, + 0.64150261, 0.76281076, 1.00000000, + 0.64102399, 0.76247267, 1.00000000, + 0.64055061, 0.76213824, 1.00000000, + 0.64008239, 0.76180740, 1.00000000, + 0.63961926, 0.76148010, 1.00000000, + 0.63916112, 0.76115628, 1.00000000, + 0.63870790, 0.76083590, 1.00000000, + 0.63825953, 0.76051890, 1.00000000, + 0.63781592, 0.76020522, 1.00000000, + 0.63737701, 0.75989482, 1.00000000, + 0.63694273, 0.75958764, 1.00000000, + 0.63651299, 0.75928365, 1.00000000, + 0.63608774, 0.75898278, 1.00000000, + 0.63566691, 0.75868499, 1.00000000, + 0.63525042, 0.75839025, 1.00000000, + 0.63483822, 0.75809849, 1.00000000, + 0.63443023, 0.75780969, 1.00000000, + 0.63402641, 0.75752379, 1.00000000, + 0.63362667, 0.75724075, 1.00000000, + 0.63323097, 0.75696053, 1.00000000, + 0.63283925, 0.75668310, 1.00000000, + 0.63245144, 0.75640840, 1.00000000, + 0.63206749, 0.75613641, 1.00000000, + 0.63168735, 0.75586707, 1.00000000, + 0.63131096, 0.75560036, 1.00000000, + 0.63093826, 0.75533624, 1.00000000, + 0.63056920, 0.75507467, 1.00000000, + 0.63020374, 0.75481562, 1.00000000, + 0.62984181, 0.75455904, 1.00000000, + 0.62948337, 0.75430491, 1.00000000, + 0.62912838, 0.75405319, 1.00000000, + 0.62877678, 0.75380385, 1.00000000, + 0.62842852, 0.75355685, 1.00000000, + 0.62808356, 0.75331217, 1.00000000, + 0.62774186, 0.75306977, 1.00000000, /* 25000K */ + 0.62740336, 0.75282962, 1.00000000 /* 25100K */ +}; + + +static void +interpolate_color(float a, const float *c1, const float *c2, float *c) +{ + c[0] = (1.0-a)*c1[0] + a*c2[0]; + c[1] = (1.0-a)*c1[1] + a*c2[1]; + c[2] = (1.0-a)*c1[2] + a*c2[2]; +} + +/* Helper macro used in the fill functions */ +#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) +{ + /* 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]/(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 \ No newline at end of file From 330e40e279780f20769ae0e5e7d9f25ad369b50c Mon Sep 17 00:00:00 2001 From: panicbit Date: Sun, 15 Apr 2018 04:51:47 +0200 Subject: [PATCH 3/7] Implement blue light filters in rosalina --- .../rosalina/include/menus/screen_filters.h | 37 +++++ sysmodules/rosalina/source/menus.c | 4 +- .../rosalina/source/menus/screen_filters.c | 144 ++++++++++++++++++ 3 files changed, 184 insertions(+), 1 deletion(-) create mode 100644 sysmodules/rosalina/include/menus/screen_filters.h create mode 100644 sysmodules/rosalina/source/menus/screen_filters.c diff --git a/sysmodules/rosalina/include/menus/screen_filters.h b/sysmodules/rosalina/include/menus/screen_filters.h new file mode 100644 index 000000000..a720e1493 --- /dev/null +++ b/sysmodules/rosalina/include/menus/screen_filters.h @@ -0,0 +1,37 @@ +/* +* This file is part of Luma3DS +* Copyright (C) 2016-2017 Aurora Wright, TuxSH +* +* This program 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. +* +* This program 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 this program. If not, see . +* +* Additional Terms 7.b and 7.c of GPLv3 apply to this file: +* * Requiring preservation of specified reasonable legal notices or +* author attributions in that material or in the Appropriate Legal +* Notices displayed by works containing it. +* * Prohibiting misrepresentation of the origin of that material, +* or requiring that modified versions of such material be marked in +* reasonable ways as different from the original version. +*/ + +#pragma once + +extern Menu screenFiltersMenu; + +void screenFiltersSetDisabled(void); +void screenFiltersReduceBlueLevel1(void); +void screenFiltersReduceBlueLevel2(void); +void screenFiltersReduceBlueLevel3(void); +void screenFiltersReduceBlueLevel4(void); +void screenFiltersReduceBlueLevel5(void); +void screenFiltersSetTemperature(int temperature); diff --git a/sysmodules/rosalina/source/menus.c b/sysmodules/rosalina/source/menus.c index b45aeb08d..6f7456f05 100644 --- a/sysmodules/rosalina/source/menus.c +++ b/sysmodules/rosalina/source/menus.c @@ -35,19 +35,21 @@ #include "menus/debugger.h" #include "menus/miscellaneous.h" #include "menus/sysconfig.h" +#include "menus/screen_filters.h" #include "ifile.h" #include "memory.h" #include "fmt.h" Menu rosalinaMenu = { "Rosalina menu", - .nbItems = 9, + .nbItems = 10, { { "Process list", METHOD, .method = &RosalinaMenu_ProcessList }, { "Take screenshot (slow!)", METHOD, .method = &RosalinaMenu_TakeScreenshot }, { "New 3DS menu...", MENU, .menu = &N3DSMenu }, { "Debugger options...", MENU, .menu = &debuggerMenu }, { "System configuration...", MENU, .menu = &sysconfigMenu }, + { "Screen filters...", MENU, .menu = &screenFiltersMenu }, { "Miscellaneous options...", MENU, .menu = &miscellaneousMenu }, { "Power off", METHOD, .method = &RosalinaMenu_PowerOff }, { "Reboot", METHOD, .method = &RosalinaMenu_Reboot }, diff --git a/sysmodules/rosalina/source/menus/screen_filters.c b/sysmodules/rosalina/source/menus/screen_filters.c new file mode 100644 index 000000000..b6b07982f --- /dev/null +++ b/sysmodules/rosalina/source/menus/screen_filters.c @@ -0,0 +1,144 @@ +/* +* This file is part of Luma3DS +* Copyright (C) 2017-2018 Sono (https://github.com/MarcuzD), panicbit +* +* This program 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. +* +* This program 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 this program. If not, see . +* +* Additional Terms 7.b and 7.c of GPLv3 apply to this file: +* * Requiring preservation of specified reasonable legal notices or +* author attributions in that material or in the Appropriate Legal +* Notices displayed by works containing it. +* * Prohibiting misrepresentation of the origin of that material, +* or requiring that modified versions of such material be marked in +* reasonable ways as different from the original version. +*/ + +#include <3ds.h> +#include "memory.h" +#include "menu.h" +#include "menus/screen_filters.h" +#include "draw.h" +#include "redshift/redshift.h" +#include "redshift/colorramp.h" + +#define TEMP_DEFAULT NEUTRAL_TEMP + +void writeLut(u32* lut) +{ + u8 idx = 0; + do { + u32 pos = idx & 0xFF; + + GPU_FB_TOP_COL_LUT_INDEX = pos; + GPU_FB_TOP_COL_LUT_ELEM = *lut; + GPU_FB_BOTTOM_COL_LUT_INDEX = pos; + GPU_FB_BOTTOM_COL_LUT_ELEM = *lut; + + lut++; + } while(++idx); +} + +typedef struct { + u8 r; + u8 g; + u8 b; + u8 z; +} Pixel; + +void applyColorSettings(color_setting_t* cs) +{ + u16 c[0x600]; + Pixel px[0x400]; + u8 i = 0; + + memset(c, 0, 0x600); + memset(px, 0, 0x400 * sizeof(Pixel)); + + do { + *(u32*)&px[i] = i | (i << 8) | (i << 16); + } while(++i); + + do { + *(c + i + 0x000) = px[i].r | (px[i].r << 8); + *(c + i + 0x100) = px[i].g | (px[i].g << 8); + *(c + i + 0x200) = px[i].b | (px[i].b << 8); + } while(++i); + + colorramp_fill(c + 0x000, c + 0x100, c + 0x200, 0x100, cs); + + do { + px[i].r = *(c + i + 0x000) >> 8; + px[i].g = *(c + i + 0x100) >> 8; + px[i].b = *(c + i + 0x200) >> 8; + } while(++i); + + writeLut((u32*)px); +} + +Menu screenFiltersMenu = { + "Screen filters menu", + .nbItems = 6, + { + { "Disable", METHOD, .method = &screenFiltersSetDisabled }, + { "Reduce blue light (level 1)", METHOD, .method = &screenFiltersReduceBlueLevel1 }, + { "Reduce blue light (level 2)", METHOD, .method = &screenFiltersReduceBlueLevel2 }, + { "Reduce blue light (level 3)", METHOD, .method = &screenFiltersReduceBlueLevel3 }, + { "Reduce blue light (level 4)", METHOD, .method = &screenFiltersReduceBlueLevel4 }, + { "Reduce blue light (level 5)", METHOD, .method = &screenFiltersReduceBlueLevel5 }, + } +}; + +void screenFiltersSetDisabled(void) +{ + screenFiltersSetTemperature(TEMP_DEFAULT); +} + +void screenFiltersReduceBlueLevel1(void) +{ + screenFiltersSetTemperature(4300); +} + +void screenFiltersReduceBlueLevel2(void) +{ + screenFiltersSetTemperature(3200); +} + +void screenFiltersReduceBlueLevel3(void) +{ + screenFiltersSetTemperature(2100); +} + +void screenFiltersReduceBlueLevel4(void) +{ + screenFiltersSetTemperature(1550); +} + +void screenFiltersReduceBlueLevel5(void) +{ + screenFiltersSetTemperature(1000); +} + +void screenFiltersSetTemperature(int temperature) +{ + color_setting_t cs; + memset(&cs, 0, sizeof(cs)); + + cs.temperature = temperature; + cs.gamma[0] = 1.0F; + cs.gamma[1] = 1.0F; + cs.gamma[2] = 1.0F; + cs.brightness = 1.0F; + + applyColorSettings(&cs); +} From 1bc50475a989fd0f0e469828a30bfa87f27df2a6 Mon Sep 17 00:00:00 2001 From: panicbit Date: Sun, 15 Apr 2018 16:26:20 +0200 Subject: [PATCH 4/7] Apply screen filter when waking up from standby --- .../rosalina/include/menus/screen_filters.h | 6 +- sysmodules/rosalina/include/shell_open.h | 30 ++++++++ sysmodules/rosalina/rosalina.rsf | 4 + sysmodules/rosalina/source/main.c | 8 +- sysmodules/rosalina/source/menu.c | 2 +- .../rosalina/source/menus/screen_filters.c | 20 +++-- sysmodules/rosalina/source/shell_open.c | 77 +++++++++++++++++++ 7 files changed, 137 insertions(+), 10 deletions(-) create mode 100644 sysmodules/rosalina/include/shell_open.h create mode 100644 sysmodules/rosalina/source/shell_open.c diff --git a/sysmodules/rosalina/include/menus/screen_filters.h b/sysmodules/rosalina/include/menus/screen_filters.h index a720e1493..21a1c7dff 100644 --- a/sysmodules/rosalina/include/menus/screen_filters.h +++ b/sysmodules/rosalina/include/menus/screen_filters.h @@ -26,12 +26,16 @@ #pragma once +#include "menu.h" + extern Menu screenFiltersMenu; +int screenFiltersCurrentTemperature; + void screenFiltersSetDisabled(void); void screenFiltersReduceBlueLevel1(void); void screenFiltersReduceBlueLevel2(void); void screenFiltersReduceBlueLevel3(void); void screenFiltersReduceBlueLevel4(void); void screenFiltersReduceBlueLevel5(void); -void screenFiltersSetTemperature(int temperature); +void screenFiltersSetTemperature(int temperature); \ No newline at end of file diff --git a/sysmodules/rosalina/include/shell_open.h b/sysmodules/rosalina/include/shell_open.h new file mode 100644 index 000000000..785ac1feb --- /dev/null +++ b/sysmodules/rosalina/include/shell_open.h @@ -0,0 +1,30 @@ +/* +* This file is part of Luma3DS +* Copyright (C) 2016-2017 Aurora Wright, TuxSH, panicbit +* +* This program 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. +* +* This program 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 this program. If not, see . +* +* Additional Terms 7.b and 7.c of GPLv3 apply to this file: +* * Requiring preservation of specified reasonable legal notices or +* author attributions in that material or in the Appropriate Legal +* Notices displayed by works containing it. +* * Prohibiting misrepresentation of the origin of that material, +* or requiring that modified versions of such material be marked in +* reasonable ways as different from the original version. +*/ + +#include + +MyThread *shellOpenCreateThread(void); +void shellOpenThreadMain(void); diff --git a/sysmodules/rosalina/rosalina.rsf b/sysmodules/rosalina/rosalina.rsf index 67d62b570..f2f256d71 100644 --- a/sysmodules/rosalina/rosalina.rsf +++ b/sysmodules/rosalina/rosalina.rsf @@ -50,8 +50,12 @@ AccessControlInfo: # The kernel extension removes svc perms checks, so below is just to avoid a makerom error Backdoor: 123 KernelSetState: 124 + BindInterrupt: 80 + UnbindInterrupt: 81 InterruptNumbers: + - 0x60 # Shell opened + ServiceAccessControl: - fs:USER # Not strictly needed as rosalina has access to everything, it's rather to avoid a makerom warning FileSystemAccess: diff --git a/sysmodules/rosalina/source/main.c b/sysmodules/rosalina/source/main.c index e75ffac86..ba4f1db39 100644 --- a/sysmodules/rosalina/source/main.c +++ b/sysmodules/rosalina/source/main.c @@ -35,6 +35,8 @@ #include "MyThread.h" #include "menus/process_patches.h" #include "menus/miscellaneous.h" +#include "menus/screen_filters.h" +#include "shell_open.h" // this is called before main bool isN3DS; @@ -99,14 +101,15 @@ int main(void) Result res = 0; Handle notificationHandle; - MyThread *menuThread = menuCreateThread(), *errDispThread = errDispCreateThread(), *hbldrThread = hbldrCreateThread(); - if(R_FAILED(srvEnableNotification(¬ificationHandle))) svcBreak(USERBREAK_ASSERT); if(R_FAILED(svcCreateEvent(&terminationRequestEvent, RESET_STICKY))) svcBreak(USERBREAK_ASSERT); + MyThread *menuThread = menuCreateThread(), *errDispThread = errDispCreateThread(), *hbldrThread = hbldrCreateThread(); + MyThread *shellOpenThread = shellOpenCreateThread(); + do { res = svcWaitSynchronization(notificationHandle, -1LL); @@ -131,6 +134,7 @@ int main(void) MyThread_Join(menuThread, -1LL); MyThread_Join(errDispThread, -1LL); MyThread_Join(hbldrThread, -1LL); + MyThread_Join(shellOpenThread, -1LL); svcCloseHandle(notificationHandle); return 0; diff --git a/sysmodules/rosalina/source/menu.c b/sysmodules/rosalina/source/menu.c index ab010a462..72162d2d9 100644 --- a/sysmodules/rosalina/source/menu.c +++ b/sysmodules/rosalina/source/menu.c @@ -129,7 +129,7 @@ static u8 batteryLevel = 255; MyThread *menuCreateThread(void) { - if(R_FAILED(MyThread_Create(&menuThread, menuThreadMain, menuThreadStack, THREAD_STACK_SIZE, 52, CORE_SYSTEM))) + if(R_FAILED(MyThread_Create(&menuThread, menuThreadMain, menuThreadStack, 0x3000, 52, CORE_SYSTEM))) svcBreak(USERBREAK_PANIC); return &menuThread; } diff --git a/sysmodules/rosalina/source/menus/screen_filters.c b/sysmodules/rosalina/source/menus/screen_filters.c index b6b07982f..a2265d676 100644 --- a/sysmodules/rosalina/source/menus/screen_filters.c +++ b/sysmodules/rosalina/source/menus/screen_filters.c @@ -34,6 +34,8 @@ #define TEMP_DEFAULT NEUTRAL_TEMP +int screenFiltersCurrentTemperature = TEMP_DEFAULT; + void writeLut(u32* lut) { u8 idx = 0; @@ -101,32 +103,38 @@ Menu screenFiltersMenu = { void screenFiltersSetDisabled(void) { - screenFiltersSetTemperature(TEMP_DEFAULT); + screenFiltersCurrentTemperature = TEMP_DEFAULT; + screenFiltersSetTemperature(screenFiltersCurrentTemperature); } void screenFiltersReduceBlueLevel1(void) { - screenFiltersSetTemperature(4300); + screenFiltersCurrentTemperature = 4300; + screenFiltersSetTemperature(screenFiltersCurrentTemperature); } void screenFiltersReduceBlueLevel2(void) { - screenFiltersSetTemperature(3200); + screenFiltersCurrentTemperature = 3200; + screenFiltersSetTemperature(screenFiltersCurrentTemperature); } void screenFiltersReduceBlueLevel3(void) { - screenFiltersSetTemperature(2100); + screenFiltersCurrentTemperature = 2100; + screenFiltersSetTemperature(screenFiltersCurrentTemperature); } void screenFiltersReduceBlueLevel4(void) { - screenFiltersSetTemperature(1550); + screenFiltersCurrentTemperature = 1550; + screenFiltersSetTemperature(screenFiltersCurrentTemperature); } void screenFiltersReduceBlueLevel5(void) { - screenFiltersSetTemperature(1000); + screenFiltersCurrentTemperature = 1000; + screenFiltersSetTemperature(screenFiltersCurrentTemperature); } void screenFiltersSetTemperature(int temperature) diff --git a/sysmodules/rosalina/source/shell_open.c b/sysmodules/rosalina/source/shell_open.c new file mode 100644 index 000000000..c6a77a4a0 --- /dev/null +++ b/sysmodules/rosalina/source/shell_open.c @@ -0,0 +1,77 @@ +/* +* This file is part of Luma3DS +* Copyright (C) 2016-2017 Aurora Wright, TuxSH, panicbit +* +* This program 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. +* +* This program 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 this program. If not, see . +* +* Additional Terms 7.b and 7.c of GPLv3 apply to this file: +* * Requiring preservation of specified reasonable legal notices or +* author attributions in that material or in the Appropriate Legal +* Notices displayed by works containing it. +* * Prohibiting misrepresentation of the origin of that material, +* or requiring that modified versions of such material be marked in +* reasonable ways as different from the original version. +*/ + +#include "shell_open.h" +#include "menus/screen_filters.h" +#include "draw.h" + +#define INT_SHELL_OPEN 0x60 +#define STACK_SIZE 0x3000 + +static MyThread shellOpenThread; +static u8 ALIGN(8) shellOpenStack[STACK_SIZE]; +static Handle shellOpenEvent; + +extern Handle terminationRequestEvent; + +MyThread *shellOpenCreateThread(void) +{ + if (R_FAILED(MyThread_Create(&shellOpenThread, shellOpenThreadMain, shellOpenStack, STACK_SIZE, 0x3F, CORE_SYSTEM))) + svcBreak(USERBREAK_PANIC); + return &shellOpenThread; +} + +void shellOpenThreadMain(void) { + if (R_FAILED(svcCreateEvent(&shellOpenEvent, RESET_ONESHOT))) + svcBreak(USERBREAK_ASSERT); + + if (R_FAILED(svcBindInterrupt(INT_SHELL_OPEN, shellOpenEvent, 0, false))) + svcBreak(USERBREAK_ASSERT); + + Handle handles[2] = {terminationRequestEvent, shellOpenEvent}; + + while (true) { + s32 idx = -1; + + svcWaitSynchronizationN(&idx, handles, 2, false, U64_MAX); + + if (idx < 0) { + continue; + } + + if (handles[idx] == terminationRequestEvent) { + break; + } + + // Need to wait for the GPU to get initialized + svcSleepThread(16 * 1000 * 1000LL); + + screenFiltersSetTemperature(screenFiltersCurrentTemperature); + } + + svcUnbindInterrupt(INT_SHELL_OPEN, shellOpenEvent); + svcCloseHandle(shellOpenEvent); +} From ef2ea18638e48c8773c361111a7eee357e6077c7 Mon Sep 17 00:00:00 2001 From: panicbit Date: Sun, 15 Apr 2018 17:15:06 +0200 Subject: [PATCH 5/7] Remove unnecassary permission declarations --- sysmodules/rosalina/rosalina.rsf | 2 -- 1 file changed, 2 deletions(-) diff --git a/sysmodules/rosalina/rosalina.rsf b/sysmodules/rosalina/rosalina.rsf index f2f256d71..d9f09fb38 100644 --- a/sysmodules/rosalina/rosalina.rsf +++ b/sysmodules/rosalina/rosalina.rsf @@ -50,8 +50,6 @@ AccessControlInfo: # The kernel extension removes svc perms checks, so below is just to avoid a makerom error Backdoor: 123 KernelSetState: 124 - BindInterrupt: 80 - UnbindInterrupt: 81 InterruptNumbers: - 0x60 # Shell opened From f177ba2742826e26c7b71072574272dfd8e199b0 Mon Sep 17 00:00:00 2001 From: panicbit Date: Mon, 16 Apr 2018 01:28:11 +0200 Subject: [PATCH 6/7] Simplify color LUT writes --- sysmodules/rosalina/source/menus/screen_filters.c | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/sysmodules/rosalina/source/menus/screen_filters.c b/sysmodules/rosalina/source/menus/screen_filters.c index a2265d676..121d8e876 100644 --- a/sysmodules/rosalina/source/menus/screen_filters.c +++ b/sysmodules/rosalina/source/menus/screen_filters.c @@ -38,17 +38,14 @@ int screenFiltersCurrentTemperature = TEMP_DEFAULT; void writeLut(u32* lut) { - u8 idx = 0; - do { - u32 pos = idx & 0xFF; + GPU_FB_TOP_COL_LUT_INDEX = 0; + GPU_FB_BOTTOM_COL_LUT_INDEX = 0; - GPU_FB_TOP_COL_LUT_INDEX = pos; + for (int i = 0; i <= 255; i++) { GPU_FB_TOP_COL_LUT_ELEM = *lut; - GPU_FB_BOTTOM_COL_LUT_INDEX = pos; GPU_FB_BOTTOM_COL_LUT_ELEM = *lut; - lut++; - } while(++idx); + } } typedef struct { From 062d46af23bfab44652585c1511712acfdb8ee2a Mon Sep 17 00:00:00 2001 From: TuxSH Date: Thu, 21 Feb 2019 19:47:35 +0100 Subject: [PATCH 7/7] Fix menu thread stack overflow sizeof(menuThreadStack) not matching 0x3000 --- sysmodules/rosalina/source/menu.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sysmodules/rosalina/source/menu.c b/sysmodules/rosalina/source/menu.c index 72162d2d9..df04b47ac 100644 --- a/sysmodules/rosalina/source/menu.c +++ b/sysmodules/rosalina/source/menu.c @@ -124,7 +124,7 @@ u32 waitCombo(void) } static MyThread menuThread; -static u8 ALIGN(8) menuThreadStack[THREAD_STACK_SIZE]; +static u8 ALIGN(8) menuThreadStack[0x3000]; static u8 batteryLevel = 255; MyThread *menuCreateThread(void)