forked from enlightenment/efl
Compare commits
139 Commits
master
...
devs/devil
Author | SHA1 | Date |
---|---|---|
Christopher Michael | 948a328965 | |
Christopher Michael | f6b0565b2b | |
Christopher Michael | f2b2971de7 | |
Christopher Michael | 3912427601 | |
Christopher Michael | 0caf4c7730 | |
Christopher Michael | 2382b4ab73 | |
Christopher Michael | ef1b33598b | |
Christopher Michael | 616165e949 | |
Christopher Michael | 430dee86e4 | |
Christopher Michael | 862115284a | |
Christopher Michael | 6478f99851 | |
Christopher Michael | 0d0e6fedbc | |
Christopher Michael | d8e6231f96 | |
Christopher Michael | 0272285970 | |
Christopher Michael | 12f1b1db9c | |
Christopher Michael | 7a00b69f4c | |
Christopher Michael | 0b64497d9b | |
Christopher Michael | ad1cf3fe75 | |
Christopher Michael | 087665ab83 | |
Ryan Gammon | 03901109ff | |
Dmitri Chudinov | 9c0eac8092 | |
Dmitri Chudinov | 79358a6214 | |
Vincent Torri | 5f6d983ca6 | |
Carsten Haitzler | 153c1cee20 | |
Carsten Haitzler | 26fc784139 | |
Carsten Haitzler | 961a03fef7 | |
Vincent Torri | bd9856ac41 | |
Carsten Haitzler | 45d468ebcb | |
Carsten Haitzler | dcb0f58902 | |
Carsten Haitzler | cf1e051e3d | |
Carsten Haitzler | a150f68a6f | |
Carsten Haitzler | 290b2fca64 | |
Vincent Torri | 5f8ecbff8f | |
Vincent Torri | 214fd63f70 | |
Vincent Torri | c9fc2d9e39 | |
Vincent Torri | a9c3e325be | |
Vincent Torri | b16feda164 | |
Carsten Haitzler | 17f886ba94 | |
Ryan Gammon | eb31861f20 | |
Ryan Gammon | 616d79b186 | |
Ryan Gammon | 9fad717133 | |
Ryan Gammon | 9c56164f1f | |
Ryan Gammon | 1517fcd575 | |
Boris Faure | 7cb584861f | |
Dmitri Chudinov | e955cb8363 | |
Dmitri Chudinov | 4fc3d14727 | |
Carsten Haitzler | 933020bc00 | |
Christopher Michael | f33c64d765 | |
Carsten Haitzler | b521d9194c | |
Carsten Haitzler | 592f1318a4 | |
Carsten Haitzler | cdbbf0b1e5 | |
Carsten Haitzler | 0938f4db5a | |
Carsten Haitzler | 2de869c0c7 | |
Vincent Torri | cffab0e3a9 | |
Vincent Torri | 84a0f83d70 | |
Vincent Torri | 3f423885ae | |
Carsten Haitzler | 0816cfe359 | |
Carsten Haitzler | 2a9667d662 | |
Vincent Torri | b492f6967e | |
Carsten Haitzler | d548a6bffb | |
Carsten Haitzler | a738ecf88e | |
Christopher Michael | 2b8b27ef5e | |
Christopher Michael | 2ac01d0db7 | |
Christopher Michael | 0aecba7277 | |
Christopher Michael | 62f8ea49fa | |
Christopher Michael | 57caf9a1bb | |
Carsten Haitzler | a16e80d8ef | |
Carsten Haitzler | 7d22469674 | |
Carsten Haitzler | 34c5c1615d | |
Carsten Haitzler | c682ec84cd | |
NorwayFun | 22e9f67abe | |
NorwayFun | a3e14e6fb8 | |
hugok | b6c013a99a | |
Carsten Haitzler | 9941a2bdd8 | |
Carsten Haitzler | e79f4719b5 | |
Carsten Haitzler | 9204209bc5 | |
Carsten Haitzler | b3e3fb12c4 | |
Christopher Michael | 5929cd7fa9 | |
Christopher Michael | 4a8b57192a | |
Carsten Haitzler | 00a44b4169 | |
Carsten Haitzler | 3468ca129a | |
Christopher Michael | f85f6f5ad2 | |
Christopher Michael | 7b19fbe81c | |
Christopher Michael | 5664911df8 | |
Christopher Michael | cf2a325012 | |
Christopher Michael | 5278c54839 | |
Christopher Michael | 28e9ef0ec0 | |
Christopher Michael | f02385bd09 | |
Christopher Michael | b8a257b7d6 | |
Christopher Michael | 3a635f0f98 | |
Christopher Michael | 69ecb57c2b | |
Christopher Michael | 5574ab8707 | |
Christopher Michael | 7ce9125d1e | |
Christopher Michael | df5f13ea64 | |
Christopher Michael | 8f5f7773b3 | |
Christopher Michael | 122298af42 | |
Christopher Michael | defeaf1313 | |
Christopher Michael | 3d939077ca | |
Christopher Michael | e47a812240 | |
Christopher Michael | 06960f71ca | |
Christopher Michael | 92deac89ac | |
Christopher Michael | d22f3f389c | |
Christopher Michael | e21afd5d1a | |
Christopher Michael | 01c6609a82 | |
Christopher Michael | 4504e1d5ee | |
Christopher Michael | 3cd26bcdc2 | |
Christopher Michael | cd5afa6128 | |
Christopher Michael | 9443dd0adc | |
Christopher Michael | daeb5264a8 | |
Christopher Michael | 9d668bd8b4 | |
Christopher Michael | 0435a37a7e | |
Christopher Michael | 2948265dc2 | |
Christopher Michael | c70d27f7f3 | |
Christopher Michael | 1e4761291c | |
Christopher Michael | 3ab68831da | |
Christopher Michael | b2535043dc | |
Christopher Michael | ef070b7816 | |
Christopher Michael | eb4940d94e | |
Christopher Michael | 1e2517cf07 | |
Christopher Michael | aa64d0f37c | |
Christopher Michael | adb95075fc | |
Christopher Michael | 51ae3a1c9b | |
Christopher Michael | 2e01beadd4 | |
Christopher Michael | 5dffb60708 | |
Christopher Michael | 2958c10c93 | |
Christopher Michael | aaa694e551 | |
Christopher Michael | 94cdf5d9f2 | |
Christopher Michael | 45ef76a41f | |
Christopher Michael | df5a498859 | |
Christopher Michael | 7f24f9793a | |
Christopher Michael | e90eab4940 | |
Christopher Michael | 275e42275f | |
Christopher Michael | 75975addc0 | |
Christopher Michael | 226d306454 | |
Christopher Michael | b69bf1a6ac | |
Christopher Michael | ee17764a5f | |
Christopher Michael | ea124c0c66 | |
Christopher Michael | 1e6df64525 | |
Christopher Michael | bcd0ae0b83 |
|
@ -32,8 +32,8 @@ For more documentation please see:
|
|||
|
||||
EFL is primarily developed on Linux (GNU/Linux) and should work on
|
||||
most distributions as long as dependencies are provided. It has been
|
||||
compiled and run also on Windows (using MSYS2 + mingw-w64 - please see
|
||||
[Phabricator windows docs](https://phab.enlightenment.org/w/windows)),
|
||||
compiled and run also on Windows (using MSYS2 + mingw-w64) - please see
|
||||
[windows docs](https://www.enlightenment.org/docs/distros/windows-start.md),
|
||||
Mac OS X, FreeBSD and NetBSD.
|
||||
|
||||
## Components
|
||||
|
|
|
@ -406,6 +406,7 @@ color_tree {
|
|||
"/fg/normal/fileman/filesize/2";
|
||||
"/fg/selected/fileman/filesize/2";
|
||||
"/fg/normal/fileperm/execute";
|
||||
"/fg/normal/filegraph/bar";
|
||||
}
|
||||
":selected-alt-trans" {
|
||||
"/bg/normal/access";
|
||||
|
@ -475,6 +476,7 @@ color_tree {
|
|||
"/fg/normal/fileman/mount/off";
|
||||
"/fg/normal/progress/busy/2";
|
||||
"/fg/normal/gadgets/packagekit/pkg/low-priority";
|
||||
"/fg/normal/filegraph/bartop";
|
||||
}
|
||||
":light-high" {
|
||||
"/fg/normal/naviframe/top/overlap";
|
||||
|
|
|
@ -267,11 +267,70 @@ group { name: "e/comp/frame/default";
|
|||
color_class: "/bg/selected/comp/win";
|
||||
}
|
||||
}
|
||||
#define FOCUSGLOWSZ 20
|
||||
part { name: "focusglow"; type: RECT;
|
||||
mouse_events: 0;
|
||||
description { state: "default" 0.0;
|
||||
rel.to: "e.swallow.content";
|
||||
}
|
||||
description { state: "active" 0.0;
|
||||
inherit: "default" 0.0;
|
||||
offscale;
|
||||
rel1.offset: (0-FOCUSGLOWSZ) (0-FOCUSGLOWSZ);
|
||||
rel2.offset: (FOCUSGLOWSZ-1) (FOCUSGLOWSZ-1);
|
||||
color: 255 255 255 0; // no cc
|
||||
}
|
||||
}
|
||||
part { name: "focusglow1"; type: RECT;
|
||||
mouse_events: 0;
|
||||
description { state: "default" 0.0;
|
||||
clip_to: "focusglow";
|
||||
offscale;
|
||||
rel2.relative: 1.0 0.0;
|
||||
rel1.offset: (0-FOCUSGLOWSZ) (0-FOCUSGLOWSZ);
|
||||
rel2.offset: (FOCUSGLOWSZ-1) -1;
|
||||
color_class: "/bg/selected/comp/focusglow";
|
||||
}
|
||||
}
|
||||
part { name: "focusglow2"; type: RECT;
|
||||
mouse_events: 0;
|
||||
description { state: "default" 0.0;
|
||||
clip_to: "focusglow";
|
||||
offscale;
|
||||
rel1.relative: 0.0 1.0;
|
||||
rel1.offset: (0-FOCUSGLOWSZ) 0;
|
||||
rel2.offset: (FOCUSGLOWSZ-1) (FOCUSGLOWSZ-1);
|
||||
color_class: "/bg/selected/comp/focusglow";
|
||||
}
|
||||
}
|
||||
part { name: "focusglow3"; type: RECT;
|
||||
mouse_events: 0;
|
||||
description { state: "default" 0.0;
|
||||
clip_to: "focusglow";
|
||||
offscale;
|
||||
rel2.relative: 0.0 1.0;
|
||||
rel1.offset: (0-FOCUSGLOWSZ) 0;
|
||||
rel2.offset: -1 -1;
|
||||
color_class: "/bg/selected/comp/focusglow";
|
||||
}
|
||||
}
|
||||
part { name: "focusglow4"; type: RECT;
|
||||
mouse_events: 0;
|
||||
description { state: "default" 0.0;
|
||||
clip_to: "focusglow";
|
||||
offscale;
|
||||
rel1.relative: 1.0 0.0;
|
||||
rel1.offset: 0 0;
|
||||
rel2.offset: (FOCUSGLOWSZ-1) -1;
|
||||
color_class: "/bg/selected/comp/focusglow";
|
||||
}
|
||||
}
|
||||
#undef FOCUSGLOWSZ
|
||||
part { name: "e.swallow.content"; type: SWALLOW;
|
||||
clip_to: "focus-clipper";
|
||||
description { state: "default" 0.0;
|
||||
rel.to: "shower";
|
||||
}
|
||||
}
|
||||
}
|
||||
spacer { "gspacer";
|
||||
desc {
|
||||
|
@ -326,6 +385,21 @@ group { name: "e/comp/frame/default";
|
|||
transition: SINUSOIDAL 0.2 USE_DURATION_FACTOR 1;
|
||||
targets: "focus-clipper" "focus-shadow";
|
||||
}
|
||||
program { name: "focusbounce";
|
||||
signal: "e,state,focused"; source: "e";
|
||||
action: STATE_SET "default" 0.0;
|
||||
target: "focusglow";
|
||||
sequence {
|
||||
action: STATE_SET "active" 0.0;
|
||||
target: "focusglow";
|
||||
transition: DECELERATE 0.3 USE_DURATION_FACTOR 1;
|
||||
}
|
||||
}
|
||||
program { name: "focusbounceoff";
|
||||
signal: "e,state,unfocused"; source: "e";
|
||||
action: STATE_SET "default" 0.0;
|
||||
target: "focusglow";
|
||||
}
|
||||
/*
|
||||
program { name: "urgent1";
|
||||
signal: "e,state,urgent"; source: "e";
|
||||
|
@ -361,6 +435,15 @@ group { name: "e/comp/frame/rotate";
|
|||
alias: "e/comp/frame/rotate/fast"; // legacy
|
||||
inherit: "e/comp/frame/default";
|
||||
parts {
|
||||
part { name: "focusglow"; type: RECT;
|
||||
description { state: "default" 0.0;
|
||||
visible: 0;
|
||||
}
|
||||
description { state: "active" 0.0;
|
||||
inherit: "default" 0.0;
|
||||
visible: 0;
|
||||
}
|
||||
}
|
||||
part { name: "e.swallow.content";
|
||||
description { state: "default";
|
||||
map {
|
||||
|
@ -394,6 +477,12 @@ group { name: "e/comp/frame/rotate";
|
|||
target: "e.swallow.content";
|
||||
transition: LINEAR 0.3 USE_DURATION_FACTOR 1;
|
||||
}
|
||||
program { name: "focusbounce";
|
||||
signal: "xxx";
|
||||
}
|
||||
program { name: "focusbounceoff";
|
||||
signal: "xxx";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -427,11 +516,28 @@ group { name: "e/comp/frame/popup";
|
|||
alias: "e/comp/frame/popup/fast"; // legacy
|
||||
inherit: "e/comp/frame/default";
|
||||
parts {
|
||||
part { name: "focusglow"; type: RECT;
|
||||
description { state: "default" 0.0;
|
||||
visible: 0;
|
||||
}
|
||||
description { state: "active" 0.0;
|
||||
inherit: "default" 0.0;
|
||||
visible: 0;
|
||||
}
|
||||
}
|
||||
part { name: "focus-clipper";
|
||||
description { state: "default";
|
||||
}
|
||||
}
|
||||
}
|
||||
programs {
|
||||
program { name: "focusbounce";
|
||||
signal: "xxx";
|
||||
}
|
||||
program { name: "focusbounceoff";
|
||||
signal: "xxx";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
group { name: "e/comp/frame/none";
|
||||
|
@ -455,6 +561,15 @@ group { name: "e/comp/frame/still";
|
|||
alias: "e/comp/frame/still/fast"; // legacy
|
||||
inherit: "e/comp/frame/default";
|
||||
parts {
|
||||
part { name: "focusglow"; type: RECT;
|
||||
description { state: "default" 0.0;
|
||||
visible: 0;
|
||||
}
|
||||
description { state: "active" 0.0;
|
||||
inherit: "default" 0.0;
|
||||
visible: 0;
|
||||
}
|
||||
}
|
||||
part { name: "shower";
|
||||
description { state: "default" 0.0;
|
||||
rel1.relative: 0.0 0.0;
|
||||
|
@ -462,6 +577,14 @@ group { name: "e/comp/frame/still";
|
|||
}
|
||||
}
|
||||
}
|
||||
programs {
|
||||
program { name: "focusbounce";
|
||||
signal: "xxx";
|
||||
}
|
||||
program { name: "focusbounceoff";
|
||||
signal: "xxx";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
group { name: "e/comp/frame/menu";
|
||||
|
@ -488,6 +611,15 @@ group { name: "e/comp/frame/everything";
|
|||
alias: "e/comp/frame/everything/fast"; // legacy
|
||||
inherit: "e/comp/frame/popup";
|
||||
parts {
|
||||
part { name: "focusglow"; type: RECT;
|
||||
description { state: "default" 0.0;
|
||||
visible: 0;
|
||||
}
|
||||
description { state: "active" 0.0;
|
||||
inherit: "default" 0.0;
|
||||
visible: 0;
|
||||
}
|
||||
}
|
||||
part { name: "shadow";
|
||||
description { state: "hidden" 0.0;
|
||||
visible: 1;
|
||||
|
@ -500,6 +632,14 @@ group { name: "e/comp/frame/everything";
|
|||
}
|
||||
}
|
||||
}
|
||||
programs {
|
||||
program { name: "focusbounce";
|
||||
signal: "xxx";
|
||||
}
|
||||
program { name: "focusbounceoff";
|
||||
signal: "xxx";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
group { name: "e/comp/frame/fullscreen";
|
||||
|
|
|
@ -17,7 +17,7 @@ group { name: "e/desklock/background";
|
|||
color_class: "/bg/normal/desklock/background";
|
||||
}
|
||||
}
|
||||
program { signal: "show"; source: "";
|
||||
program { name: "shower"; signal: "show"; source: "";
|
||||
action: STATE_SET "visible" 0.0;
|
||||
transition: SINUSOIDAL 0.5 USE_DURATION_FACTOR 1;
|
||||
target: "clip";
|
||||
|
@ -30,6 +30,14 @@ group { name: "e/desklock/background";
|
|||
action: SIGNAL_EMIT "e,action,hide,done" "e";
|
||||
}
|
||||
}
|
||||
program { signal: "e,action,show,immediate"; source: "e";
|
||||
action: ACTION_STOP;
|
||||
target: "shower";
|
||||
sequence {
|
||||
action: STATE_SET "visible" 0.0;
|
||||
target: "clip";
|
||||
}
|
||||
}
|
||||
part { name: "e.swallow.login_box"; type: SWALLOW;
|
||||
clip_to: "clip";
|
||||
description { state: "default" 0.0;
|
||||
|
|
|
@ -908,3 +908,301 @@ group { name: "elm/radio/base/icon";
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
group { name: "elm/radio/base/sort_header";
|
||||
script {
|
||||
BUTTONMODE_SCRIPT
|
||||
public sel;
|
||||
public eval_sel(m) {
|
||||
if (m) {
|
||||
set_state(PART:"ck_check", "selected", 0.0);
|
||||
} else {
|
||||
set_state(PART:"ck_check", "default", 0.0);
|
||||
}
|
||||
}
|
||||
}
|
||||
parts {
|
||||
part { name: "shadow"; type: SPACER;
|
||||
description { state: "default";
|
||||
}
|
||||
desc { "pressed"; inherit;
|
||||
}
|
||||
desc { "disabled"; inherit;
|
||||
}
|
||||
}
|
||||
swallow { "elm.swallow.background"; nomouse;
|
||||
desc { "default";
|
||||
visible: 0;
|
||||
}
|
||||
desc { "visible"; inherit;
|
||||
visible: 1;
|
||||
}
|
||||
}
|
||||
rect { "icon_clip";
|
||||
desc { "default";
|
||||
color: 255 255 255 255; // no cc
|
||||
}
|
||||
desc { "pressed"; inherit;
|
||||
color: 255 255 255 255; // no cc
|
||||
}
|
||||
desc { "disabled"; inherit;
|
||||
color: 255 255 255 64; // no cc
|
||||
}
|
||||
}
|
||||
swallow { "elm.swallow.content"; nomouse;
|
||||
clip_to: "icon_clip";
|
||||
scale: 1;
|
||||
desc { "default";
|
||||
fixed: 1 0;
|
||||
align: 0.0 0.5;
|
||||
rel1.to_x: "base";
|
||||
rel2.to_x: "base";
|
||||
rel1.offset: 4 4;
|
||||
rel1.relative: 1.0 0.0;
|
||||
rel2.relative: 0.0 1.0;
|
||||
rel2.offset: 4 -5;
|
||||
visible: 0;
|
||||
offscale;
|
||||
}
|
||||
desc { "visible"; inherit;
|
||||
fixed: 1 0;
|
||||
aspect: 1.0 1.0;
|
||||
min: ICMIN ICMIN;
|
||||
visible: 1;
|
||||
}
|
||||
desc { "icononly"; inherit;
|
||||
fixed: 0 0;
|
||||
align: 0.5 0.5;
|
||||
rel2.relative: 1.0 1.0;
|
||||
rel2.offset: -5 -5;
|
||||
rel2.to_x: "";
|
||||
visible: 1;
|
||||
min: ICMIN ICMIN;
|
||||
}
|
||||
}
|
||||
part { name: "base"; type: RECT;
|
||||
scale: 1;
|
||||
description { state: "default";
|
||||
fixed: 1 0;
|
||||
align: 0.0 0.5;
|
||||
min: 13 13;
|
||||
max: 13 13;
|
||||
rel1.offset: 4 4;
|
||||
rel2.relative: 0.0 1.0;
|
||||
rel2.offset: 4 -5;
|
||||
aspect: 1.0 1.0; aspect_preference: VERTICAL;
|
||||
offscale;
|
||||
visible: 0;
|
||||
offscale;
|
||||
}
|
||||
desc { "pressed"; inherit;
|
||||
}
|
||||
desc { "disabled"; inherit;
|
||||
}
|
||||
}
|
||||
part { name: "ck_bg";
|
||||
scale: 1;
|
||||
description { state: "default" 0.0;
|
||||
fixed: 1 1;
|
||||
rel.to: "base";
|
||||
image.normal: "i-arrow-d";
|
||||
min: 15 15;
|
||||
max: 15 15;
|
||||
color_class: "/bg/normal/radio/base";
|
||||
}
|
||||
desc { "disabled"; inherit;
|
||||
color_class: "/bg/disabled/radio/base";
|
||||
}
|
||||
}
|
||||
part { name: "ck_check";
|
||||
scale: 1;
|
||||
description { state: "default" 0.0;
|
||||
color_class: "/fg/selected/radio/radio";
|
||||
rel.to: "base";
|
||||
image.normal: "i-arrow-d";
|
||||
min: 15 15;
|
||||
max: 15 15;
|
||||
fixed: 1 1;
|
||||
visible: 0;
|
||||
}
|
||||
description { state: "selected" 0.0;
|
||||
inherit: "default" 0.0;
|
||||
visible: 1;
|
||||
}
|
||||
desc { "disabled"; inherit;
|
||||
visible: 0;
|
||||
}
|
||||
}
|
||||
part { name: "ck_press";
|
||||
scale: 1;
|
||||
description { state: "default" 0.0;
|
||||
color_class: "/fg/pressed/radio/radio";
|
||||
fixed: 1 1;
|
||||
rel.to: "base";
|
||||
image.normal: "i-arrow-d";
|
||||
min: 15 15;
|
||||
max: 15 15;
|
||||
visible: 0;
|
||||
}
|
||||
description { state: "pressed" 0.0;
|
||||
inherit: "default" 0.0;
|
||||
visible: 1;
|
||||
}
|
||||
}
|
||||
text { "elm.text"; nomouse;
|
||||
scale: 1;
|
||||
desc { "default";
|
||||
fixed: 0 1;
|
||||
color_class: "/fg/normal/radio/text";
|
||||
rel1.offset: 0 4;
|
||||
rel1.relative: 1.0 0.0;
|
||||
rel1.to_x: "elm.swallow.content";
|
||||
rel2.offset: -5 -5;
|
||||
text { font: FN; size: 10;
|
||||
align: 0.0 0.5;
|
||||
min: 0 0;
|
||||
ellipsis: 0;
|
||||
}
|
||||
visible: 0;
|
||||
offscale;
|
||||
min: 0 ICMIN;
|
||||
}
|
||||
desc { "visible"; inherit;
|
||||
fixed: 0 0;
|
||||
rel1.offset: 4 4;
|
||||
// text.min: 1 1;
|
||||
// text.ellipsis: -1;
|
||||
visible: 1;
|
||||
}
|
||||
desc { "pressed_visible"; inherit;
|
||||
fixed: 0 0;
|
||||
color_class: "/fg/pressed/radio/text";
|
||||
rel1.offset: 4 4;
|
||||
// text.min: 1 1;
|
||||
// text.ellipsis: -1;
|
||||
visible: 1;
|
||||
}
|
||||
desc { "textonly"; inherit;
|
||||
fixed: 0 0;
|
||||
// text.min: 1 1;
|
||||
// text.ellipsis: -1;
|
||||
visible: 1;
|
||||
}
|
||||
desc { "pressed_textonly"; inherit;
|
||||
fixed: 0 0;
|
||||
color_class: "/fg/pressed/radio/text";
|
||||
// text.min: 1 1;
|
||||
// text.ellipsis: -1;
|
||||
visible: 1;
|
||||
}
|
||||
desc { "disabled_visible"; inherit;
|
||||
fixed: 0 0;
|
||||
color_class: "/fg/disabled/radio/text";
|
||||
rel1.offset: 4 4;
|
||||
// text.min: 1 1;
|
||||
// text.ellipsis: -1;
|
||||
visible: 1;
|
||||
}
|
||||
desc { "disabled_textonly"; inherit;
|
||||
fixed: 0 0;
|
||||
color_class: "/fg/disabled/radio/text";
|
||||
// text.min: 1 1;
|
||||
// text.ellipsis: -1;
|
||||
visible: 1;
|
||||
}
|
||||
}
|
||||
rect { "event";
|
||||
ignore_flags: ON_HOLD;
|
||||
desc { "default";
|
||||
color: 0 0 0 0; // no cc
|
||||
}
|
||||
desc { "disabled"; inherit;
|
||||
visible: 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
programs {
|
||||
program { signal: "mouse,clicked,1"; source: "event";
|
||||
action: SIGNAL_EMIT "elm,action,radio,toggle" "elm";
|
||||
}
|
||||
program { signal: "elm,state,radio,on"; source: "elm";
|
||||
script {
|
||||
new m = get_int(sel) | SELECTED;
|
||||
set_int(sel, m);
|
||||
eval_sel(m);
|
||||
}
|
||||
}
|
||||
program { signal: "elm,state,radio,off"; source: "elm";
|
||||
script {
|
||||
new m = get_int(sel) & ~SELECTED;
|
||||
set_int(sel, m);
|
||||
eval_sel(m);
|
||||
}
|
||||
}
|
||||
program { signal: "mouse,down,1"; source: "event";
|
||||
action: SIGNAL_EMIT "elm,action,press" "elm";
|
||||
after: "button_click_anim";
|
||||
}
|
||||
program { name: "button_click_anim";
|
||||
script { flag_set(PRESSED); }
|
||||
}
|
||||
program { signal: "mouse,down,1"; source: "event";
|
||||
script { eval_sel(get_int(sel) | SELECTED); }
|
||||
}
|
||||
program { signal: "mouse,up,1"; source: "event";
|
||||
action: SIGNAL_EMIT "elm,action,unpress" "elm";
|
||||
after: "button_unclick_anim";
|
||||
}
|
||||
program { name: "button_unclick_anim";
|
||||
script { flag_unset(PRESSED); }
|
||||
}
|
||||
program { signal: "mouse,up,1"; source: "event";
|
||||
script { eval_sel(get_int(sel)); }
|
||||
}
|
||||
program { signal: "mouse,clicked,1"; source: "event";
|
||||
action: SIGNAL_EMIT "elm,action,click" "elm";
|
||||
}
|
||||
program { signal: "elm,state,text,visible"; source: "elm";
|
||||
script { flag_set(LABEL); }
|
||||
}
|
||||
program { signal: "elm,state,text,hidden"; source: "elm";
|
||||
script { flag_unset(LABEL); }
|
||||
}
|
||||
program { signal: "elm,state,icon,visible"; source: "elm";
|
||||
script { flag_set(ICON); }
|
||||
}
|
||||
program { signal: "elm,state,icon,hidden"; source: "elm";
|
||||
script { flag_unset(ICON); }
|
||||
}
|
||||
program { signal: "elm,state,background,visible"; source: "elm";
|
||||
script { flag_set(BACKGROUND); }
|
||||
}
|
||||
program { signal: "elm,state,background,hidden"; source: "elm";
|
||||
script { flag_unset(BACKGROUND); }
|
||||
}
|
||||
program { signal: "elm,state,disabled"; source: "elm";
|
||||
script { flag_set(DISABLE); }
|
||||
}
|
||||
program { signal: "elm,state,enabled"; source: "elm";
|
||||
script { flag_unset(DISABLE); }
|
||||
}
|
||||
program { signal: "elm,state,disabled"; source: "elm";
|
||||
action: STATE_SET "disabled" 0.0;
|
||||
target: "ck_check";
|
||||
target: "ck_bg";
|
||||
}
|
||||
program { signal: "elm,state,enabled"; source: "elm";
|
||||
action: STATE_SET "default" 0.0;
|
||||
target: "ck_check";
|
||||
target: "ck_bg";
|
||||
}
|
||||
program { signal: "mouse,down,1"; source: "event";
|
||||
action: STATE_SET "pressed" 0.0;
|
||||
target: "ck_press";
|
||||
}
|
||||
program { signal: "mouse,up,1"; source: "event";
|
||||
action: STATE_SET "default" 0.0;
|
||||
target: "ck_press";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -28,16 +28,12 @@ group { name: "elm/scroller/base/default";
|
|||
}
|
||||
part { name: "clipper"; type: RECT;
|
||||
description { state: "default" 0.0;
|
||||
rel.to: "elm.swallow.background";
|
||||
rel.to: "elm.swallow.content";
|
||||
}
|
||||
}
|
||||
part { name: "elm.swallow.background"; type: SWALLOW;
|
||||
// scale: 1;
|
||||
clip_to: "clipper";
|
||||
description { state: "default" 0.0;
|
||||
// rel1.offset: 2 2;
|
||||
// rel2.offset: -3 -3;
|
||||
// offscale;
|
||||
}
|
||||
}
|
||||
part { name: "elm.swallow.content"; type: SWALLOW;
|
||||
|
@ -187,7 +183,7 @@ group { name: "elm/scroller/base/default";
|
|||
|
||||
part { name: "sh_clip"; type: RECT;
|
||||
description { state: "default" 0.0;
|
||||
rel.to: "elm.swallow.background";
|
||||
rel.to: "clipper";
|
||||
}
|
||||
}
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
|
|
|
@ -335,7 +335,7 @@ group { name: "elm/slider/horizontal/default";
|
|||
rel2.to_x: "elm.swallow.bar";
|
||||
}
|
||||
}
|
||||
part { name: "knob"; repeat_events: 1;
|
||||
part { name: "knob"; mouse_events: 0;
|
||||
scale: 1;
|
||||
description { state: "default" 0.0;
|
||||
fixed: 1 1;
|
||||
|
@ -354,7 +354,7 @@ group { name: "elm/slider/horizontal/default";
|
|||
color_class: "/fg/disabled/slider/knob";
|
||||
}
|
||||
}
|
||||
part { name: "slideevent"; type: RECT; repeat_events: 1;
|
||||
part { name: "slideevent"; type: RECT; repeat_events: 0;
|
||||
scale: 1;
|
||||
ignore_flags: ON_HOLD;
|
||||
dragable.events: "elm.dragable.slider";
|
||||
|
@ -947,7 +947,7 @@ group { name: "elm/slider/vertical/default";
|
|||
rel2.to_y: "elm.swallow.bar";
|
||||
}
|
||||
}
|
||||
part { name: "knob"; repeat_events: 1;
|
||||
part { name: "knob"; mouse_events: 0;
|
||||
scale: 1;
|
||||
description { state: "default" 0.0;
|
||||
fixed: 1 1;
|
||||
|
@ -966,7 +966,7 @@ group { name: "elm/slider/vertical/default";
|
|||
color_class: "/fg/disabled/slider/knob";
|
||||
}
|
||||
}
|
||||
part { name: "slideevent"; type: RECT; repeat_events: 1;
|
||||
part { name: "slideevent"; type: RECT; repeat_events: 0;
|
||||
scale: 1;
|
||||
ignore_flags: ON_HOLD;
|
||||
dragable.events: "elm.dragable.slider";
|
||||
|
@ -1614,7 +1614,7 @@ group { name: "elm/slider/range/horizontal/default";
|
|||
rel2.to_x: "elm.swallow.bar";
|
||||
}
|
||||
}
|
||||
part { name: "knob"; repeat_events: 1;
|
||||
part { name: "knob"; mouse_events: 0;
|
||||
scale: 1;
|
||||
description { state: "default" 0.0;
|
||||
fixed: 1 1;
|
||||
|
@ -1633,7 +1633,7 @@ group { name: "elm/slider/range/horizontal/default";
|
|||
color_class: "/fg/disabled/slider/knob";
|
||||
}
|
||||
}
|
||||
part { name: "slideevent"; type: RECT; repeat_events: 1;
|
||||
part { name: "slideevent"; type: RECT; repeat_events: 0;
|
||||
scale: 1;
|
||||
ignore_flags: ON_HOLD;
|
||||
dragable.events: "elm.dragable.slider";
|
||||
|
@ -1677,7 +1677,7 @@ group { name: "elm/slider/range/horizontal/default";
|
|||
rel2.to_x: "elm.swallow.bar";
|
||||
}
|
||||
}
|
||||
part { name: "knob2"; repeat_events: 1;
|
||||
part { name: "knob2"; mouse_events: 0;
|
||||
clip_to: "enable2";
|
||||
scale: 1;
|
||||
description { state: "default" 0.0;
|
||||
|
@ -1698,7 +1698,7 @@ group { name: "elm/slider/range/horizontal/default";
|
|||
color_class: "/fg/disabled/slider/knob";
|
||||
}
|
||||
}
|
||||
part { name: "slideevent2"; type: RECT; repeat_events: 1;
|
||||
part { name: "slideevent2"; type: RECT; repeat_events: 0;
|
||||
clip_to: "enable2";
|
||||
scale: 1;
|
||||
ignore_flags: ON_HOLD;
|
||||
|
@ -2298,7 +2298,7 @@ group { name: "elm/slider/range/vertical/default";
|
|||
rel2.to_y: "elm.swallow.bar";
|
||||
}
|
||||
}
|
||||
part { name: "knob"; repeat_events: 1;
|
||||
part { name: "knob"; mouse_events: 0;
|
||||
scale: 1;
|
||||
description { state: "default" 0.0;
|
||||
fixed: 1 1;
|
||||
|
@ -2317,7 +2317,7 @@ group { name: "elm/slider/range/vertical/default";
|
|||
color_class: "/fg/disabled/slider/knob";
|
||||
}
|
||||
}
|
||||
part { name: "slideevent"; type: RECT; repeat_events: 1;
|
||||
part { name: "slideevent"; type: RECT; repeat_events: 0;
|
||||
scale: 1;
|
||||
ignore_flags: ON_HOLD;
|
||||
dragable.events: "elm.dragable.slider";
|
||||
|
@ -2361,7 +2361,7 @@ group { name: "elm/slider/range/vertical/default";
|
|||
rel2.to_y: "elm.swallow.bar";
|
||||
}
|
||||
}
|
||||
part { name: "knob2"; repeat_events: 1;
|
||||
part { name: "knob2"; mouse_events: 0;
|
||||
clip_to: "enable2";
|
||||
scale: 1;
|
||||
description { state: "default" 0.0;
|
||||
|
@ -2381,7 +2381,7 @@ group { name: "elm/slider/range/vertical/default";
|
|||
color_class: "/fg/disabled/slider/knob";
|
||||
}
|
||||
}
|
||||
part { name: "slideevent2"; type: RECT; repeat_events: 1;
|
||||
part { name: "slideevent2"; type: RECT; repeat_events: 0;
|
||||
clip_to: "enable2";
|
||||
scale: 1;
|
||||
ignore_flags: ON_HOLD;
|
||||
|
|
|
@ -77,6 +77,21 @@ group { name: "e/fileman/default/list/variable";
|
|||
inherit: "default" 0.0;
|
||||
}
|
||||
}
|
||||
part { name: "icon_mono"; type: RECT;
|
||||
description { state: "default" 0.0;
|
||||
rel.to: "icon";
|
||||
color_class: "/fg/normal/grid/item";
|
||||
}
|
||||
description { state: "selected" 0.0;
|
||||
color_class: "/fg/selected/grid/item";
|
||||
}
|
||||
}
|
||||
part { name: "e.swallow.icon_mono"; type: SWALLOW; mouse_events: 0;
|
||||
clip_to: "icon_mono";
|
||||
description { state: "default" 0.0;
|
||||
rel.to: "icon0";
|
||||
}
|
||||
}
|
||||
part { name: "e.swallow.icon"; type: SWALLOW; mouse_events: 0;
|
||||
clip_to: "icon";
|
||||
description { state: "default" 0.0;
|
||||
|
@ -217,11 +232,13 @@ group { name: "e/fileman/default/list/variable";
|
|||
action: STATE_SET "selected" 0.0;
|
||||
target: "sel_base";
|
||||
target: "e.text.label";
|
||||
target: "icon_mono";
|
||||
}
|
||||
program { signal: "e,state,unselected"; source: "e";
|
||||
action: STATE_SET "default" 0.0;
|
||||
target: "sel_base";
|
||||
target: "e.text.label";
|
||||
target: "icon_mono";
|
||||
}
|
||||
program { signal: "mouse,down,1"; source: "label_event";
|
||||
script {
|
||||
|
@ -498,44 +515,37 @@ group { name: "e/fileman/default/fileperms";
|
|||
part { name: "type";
|
||||
scale: 1;
|
||||
description { state: "default" 0.0;
|
||||
image.normal: "i-folder";
|
||||
image.normal: "i-file";
|
||||
min: 15 15; max: 15 15;
|
||||
rel1.offset: 0 2;
|
||||
rel2.relative: 0.0 1.0;
|
||||
rel2.to_x: "user-setuid";
|
||||
rel2.offset: -5 -3;
|
||||
visible: 0;
|
||||
offscale;
|
||||
}
|
||||
description { state: "dir" 0.0;
|
||||
inherit: "default" 0.0;
|
||||
image.normal: "i-folder";
|
||||
visible: 1;
|
||||
}
|
||||
description { state: "link" 0.0;
|
||||
inherit: "default" 0.0;
|
||||
image.normal: "i-arrow-r";
|
||||
visible: 1;
|
||||
}
|
||||
description { state: "pipe" 0.0;
|
||||
inherit: "default" 0.0;
|
||||
image.normal: "i-device-pipe";
|
||||
visible: 1;
|
||||
}
|
||||
description { state: "socket" 0.0;
|
||||
inherit: "default" 0.0;
|
||||
image.normal: "i-device-socket";
|
||||
visible: 1;
|
||||
}
|
||||
description { state: "block" 0.0;
|
||||
inherit: "default" 0.0;
|
||||
image.normal: "i-device-block";
|
||||
visible: 1;
|
||||
}
|
||||
description { state: "char" 0.0;
|
||||
inherit: "default" 0.0;
|
||||
image.normal: "i-device-char";
|
||||
visible: 1;
|
||||
}
|
||||
}
|
||||
part { name: "user-middle"; type: SPACER;
|
||||
|
@ -1055,6 +1065,263 @@ group { name: "e/fileman/default/filedate";
|
|||
}
|
||||
}
|
||||
|
||||
group { name: "e/fileman/default/check";
|
||||
parts {
|
||||
part { name: "base";
|
||||
clip_to: "selected";
|
||||
scale: 1;
|
||||
description { state: "default" 0.0;
|
||||
image.normal: "i-check";
|
||||
rel1.offset: 3 3;
|
||||
rel2.offset: -4 -4;
|
||||
min: 15 15;
|
||||
max: 15 15;
|
||||
visible: 0;
|
||||
offscale;
|
||||
}
|
||||
description { state: "on" 0.0;
|
||||
inherit: "default" 0.0;
|
||||
visible: 1;
|
||||
}
|
||||
}
|
||||
part { name: "selected"; type: RECT;
|
||||
description { state: "default" 0.0;
|
||||
rel.to: "base";
|
||||
color_class: "/fg/normal/fileman/item/check/check";
|
||||
}
|
||||
description { state: "selected" 0.0;
|
||||
inherit: "default" 0.0;
|
||||
color_class: "/fg/selected/fileman/item/check/check";
|
||||
}
|
||||
}
|
||||
}
|
||||
programs {
|
||||
program { signal: "e,state,selected"; source: "e";
|
||||
action: STATE_SET "selected" 0.0;
|
||||
target: "selected";
|
||||
}
|
||||
program { signal: "e,state,unselected"; source: "e";
|
||||
action: STATE_SET "default" 0.0;
|
||||
target: "selected";
|
||||
}
|
||||
program { signal: "e,state,on"; source: "e";
|
||||
action: STATE_SET "on" 0.0;
|
||||
target: "base";
|
||||
}
|
||||
program { signal: "e,state,off"; source: "e";
|
||||
action: STATE_SET "default" 0.0;
|
||||
target: "base";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
group { name: "e/fileman/default/circle";
|
||||
script {
|
||||
hex(str[], len) {
|
||||
new i, val = 0;
|
||||
|
||||
for (i = 0; i < len; i++) {
|
||||
val <<= 4;
|
||||
if ((str[i] >= '0') && (str[i] <= '9')) {
|
||||
val += str[i] - '0';
|
||||
} else if ((str[i] >= 'a') && (str[i] <= 'f')) {
|
||||
val += 10 + str[i] - 'a';
|
||||
} else if ((str[i] >= 'A') && (str[i] <= 'F')) {
|
||||
val += 10 + str[i] - 'A';
|
||||
}
|
||||
}
|
||||
return val;
|
||||
}
|
||||
public message(Msg_Type:type, id, ...) {
|
||||
if ((type == MSG_STRING) && (id == 1)) {
|
||||
new cc[256];
|
||||
|
||||
getsarg(2, cc, 255);
|
||||
custom_state(PART:"base", "default", 0.0);
|
||||
if (!strncmp(cc, "cc:", 3)) {
|
||||
strcpy(cc, cc[3]);
|
||||
set_state_val(PART:"base", STATE_COLOR, 255, 255, 255, 255);
|
||||
set_state_val(PART:"base", STATE_COLOR_CLASS, cc);
|
||||
} else if (!strncmp(cc, "#", 1)) {
|
||||
new r = 255, g = 255, b = 255, a = 255;
|
||||
|
||||
strcpy(cc, cc[1]);
|
||||
if (strlen(cc) == 3) { // #35a
|
||||
r = hex(cc[0], 1);
|
||||
g = hex(cc[1], 1);
|
||||
b = hex(cc[2], 1);
|
||||
} else if (strlen(cc) == 4) { // #35af
|
||||
r = hex(cc[0], 1);
|
||||
g = hex(cc[1], 1);
|
||||
b = hex(cc[2], 1);
|
||||
a = hex(cc[3], 1);
|
||||
} else if (strlen(cc) == 6) { // #3355aa
|
||||
r = hex(cc[0], 2);
|
||||
g = hex(cc[2], 2);
|
||||
b = hex(cc[4], 2);
|
||||
} else if (strlen(cc) == 8) { // #3355aaff
|
||||
r = hex(cc[0], 2);
|
||||
g = hex(cc[2], 2);
|
||||
b = hex(cc[4], 2);
|
||||
a = hex(cc[6], 2);
|
||||
}
|
||||
set_state_val(PART:"base", STATE_COLOR, r, g, b, a);
|
||||
set_state_val(PART:"base", STATE_COLOR_CLASS, "");
|
||||
}
|
||||
set_state(PART:"base", "custom", 0.0);
|
||||
}
|
||||
}
|
||||
}
|
||||
parts {
|
||||
set { name: "file-circle-outline";
|
||||
image { image: "speaker-clip-160.png" COMP; size: 81 81 99999 99999; }
|
||||
image { image: "speaker-clip-080.png" COMP; size: 41 41 80 80 99999; }
|
||||
image { image: "speaker-clip-040.png" COMP; size: 0 0 40 40; }
|
||||
}
|
||||
part { name: "base"; mouse_events: 0;
|
||||
scale: 1;
|
||||
description { state: "default" 0.0;
|
||||
min: 15 15;
|
||||
max: 15 15;
|
||||
rel1.offset: 3 3;
|
||||
rel2.offset: -4 -4;
|
||||
image.normal: "i-radio";
|
||||
offscale;
|
||||
fixed: 1 1;
|
||||
}
|
||||
}
|
||||
part { name: "circle"; mouse_events: 0;
|
||||
scale: 1;
|
||||
description { state: "default" 0.0;
|
||||
min: 17 17;
|
||||
max: 17 17;
|
||||
rel.to: "base";
|
||||
image.normal: "file-circle-outline";
|
||||
fixed: 1 1;
|
||||
color_class: "/fg/selected/list/item";
|
||||
visible: 0;
|
||||
}
|
||||
description { state: "selected" 0.0;
|
||||
inherit: "default" 0.0;
|
||||
visible: 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
programs {
|
||||
program { signal: "e,state,selected"; source: "e";
|
||||
action: STATE_SET "selected" 0.0;
|
||||
target: "circle";
|
||||
}
|
||||
program { signal: "e,state,unselected"; source: "e";
|
||||
action: STATE_SET "default" 0.0;
|
||||
target: "circle";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
group { name: "e/fileman/default/graph/base";
|
||||
parts {
|
||||
part { name: "e.swallow.content"; type: SWALLOW; scale;
|
||||
description { state: "default" 0.0; offscale;
|
||||
rel1 { offset: 2 2; }
|
||||
rel2 { offset: -3 -3; }
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
group { name: "e/fileman/default/graph/bar";
|
||||
script {
|
||||
hex(str[], len) {
|
||||
new i, val = 0;
|
||||
|
||||
for (i = 0; i < len; i++) {
|
||||
val <<= 4;
|
||||
if ((str[i] >= '0') && (str[i] <= '9')) {
|
||||
val += str[i] - '0';
|
||||
} else if ((str[i] >= 'a') && (str[i] <= 'f')) {
|
||||
val += 10 + str[i] - 'a';
|
||||
} else if ((str[i] >= 'A') && (str[i] <= 'F')) {
|
||||
val += 10 + str[i] - 'A';
|
||||
}
|
||||
}
|
||||
return val;
|
||||
}
|
||||
public message(Msg_Type:type, id, ...) {
|
||||
if ((type == MSG_STRING) && (id == 1)) {
|
||||
new cc[256];
|
||||
|
||||
getsarg(2, cc, 255);
|
||||
custom_state(PART:"base", "default", 0.0);
|
||||
if (!strncmp(cc, "cc:", 3)) {
|
||||
strcpy(cc, cc[3]);
|
||||
set_state_val(PART:"base", STATE_COLOR, 255, 255, 255, 255);
|
||||
set_state_val(PART:"base", STATE_COLOR_CLASS, cc);
|
||||
} else if (!strncmp(cc, "#", 1)) {
|
||||
new r = 255, g = 255, b = 255, a = 255;
|
||||
|
||||
strcpy(cc, cc[1]);
|
||||
if (strlen(cc) == 3) { // #35a
|
||||
r = hex(cc[0], 1);
|
||||
g = hex(cc[1], 1);
|
||||
b = hex(cc[2], 1);
|
||||
} else if (strlen(cc) == 4) { // #35af
|
||||
r = hex(cc[0], 1);
|
||||
g = hex(cc[1], 1);
|
||||
b = hex(cc[2], 1);
|
||||
a = hex(cc[3], 1);
|
||||
} else if (strlen(cc) == 6) { // #3355aa
|
||||
r = hex(cc[0], 2);
|
||||
g = hex(cc[2], 2);
|
||||
b = hex(cc[4], 2);
|
||||
} else if (strlen(cc) == 8) { // #3355aaff
|
||||
r = hex(cc[0], 2);
|
||||
g = hex(cc[2], 2);
|
||||
b = hex(cc[4], 2);
|
||||
a = hex(cc[6], 2);
|
||||
}
|
||||
set_state_val(PART:"base", STATE_COLOR, r, g, b, a);
|
||||
set_state_val(PART:"base", STATE_COLOR_CLASS, "");
|
||||
}
|
||||
set_state(PART:"base", "custom", 0.0);
|
||||
}
|
||||
}
|
||||
}
|
||||
parts {
|
||||
part { name: "drag_base"; type: SPACER; scale;
|
||||
description { state: "default" 0.0; offscale;
|
||||
rel1 { offset: 1 1; }
|
||||
rel2 { offset: -2 -2; }
|
||||
}
|
||||
}
|
||||
part { name: "base"; type: RECT;
|
||||
description { state: "default" 0.0;
|
||||
rel1.to_y: "e.dragable.value";
|
||||
rel2.to: "drag_base";
|
||||
color_class: "/fg/normal/filegraph/bar";
|
||||
}
|
||||
}
|
||||
part { name: "top"; type: RECT;
|
||||
description { state: "default" 0.0;
|
||||
rel.to: "base";
|
||||
rel2.relative: 1.0 0.0;
|
||||
rel2.offset: -1 0;
|
||||
color_class: "/fg/normal/filegraph/bartop";
|
||||
}
|
||||
}
|
||||
part { name: "e.dragable.value"; type: SPACER;
|
||||
dragable.x: 0 0 0;
|
||||
dragable.y: 1 1 0;
|
||||
dragable.confine: "drag_base";
|
||||
description { state: "default" 0.0;
|
||||
min: 0 1;
|
||||
max: 99999 1;
|
||||
fixed: 1 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
group { name: "e/fileman/default/list/detailed";
|
||||
inherit: "e/fileman/default/list/variable";
|
||||
parts {
|
||||
|
@ -1084,6 +1351,20 @@ group { name: "e/fileman/default/list/detailed";
|
|||
color_class: "/fg/disabled/list/item"; \
|
||||
} \
|
||||
}
|
||||
part { name: "e.text.label";
|
||||
description { state: "default" 0.0;
|
||||
rel2.to_x: "e.swallow.detail1";
|
||||
rel2.relative: 0.0 1.0;
|
||||
}
|
||||
description { state: "selected" 0.0;
|
||||
rel2.to_x: "e.swallow.detail1";
|
||||
rel2.relative: 0.0 1.0;
|
||||
}
|
||||
description { state: "disabled" 0.0;
|
||||
rel2.to_x: "e.swallow.detail1";
|
||||
rel2.relative: 0.0 1.0;
|
||||
}
|
||||
}
|
||||
DETAILTEXT("e.text.detail1", "e.swallow.detail1", "e.text.label")
|
||||
DETAILTEXT("e.text.detail2", "e.swallow.detail2", "e.text.detail1")
|
||||
DETAILTEXT("e.text.detail3", "e.swallow.detail3", "e.text.detail2")
|
||||
|
@ -1109,15 +1390,15 @@ group { name: "e/fileman/default/list/detailed";
|
|||
target: "e.text.detail5";
|
||||
target: "e.text.detail6";
|
||||
}
|
||||
part { name: "e.swallow.detail6"; type: SWALLOW; nomouse; scale;
|
||||
insert_after: "e.text.detail6";
|
||||
part { name: "e.swallow.detail6"; type: SWALLOW; scale;
|
||||
insert_after: "e.swallow.entry";
|
||||
description { state: "default" 0.0; offscale;
|
||||
align: 1.0 0.5; min: 15 5;
|
||||
rel1 { offset: -5 0; relative: 1.0 0.0; }
|
||||
rel2 { offset: -5 -1; relative: 1.0 1.0; }
|
||||
}
|
||||
}
|
||||
part { name: "e.swallow.detail5"; type: SWALLOW; nomouse; scale;
|
||||
part { name: "e.swallow.detail5"; type: SWALLOW; scale;
|
||||
insert_after: "e.swallow.detail6";
|
||||
description { state: "default" 0.0; offscale;
|
||||
align: 1.0 0.5; min: 20 5;
|
||||
|
@ -1125,7 +1406,7 @@ group { name: "e/fileman/default/list/detailed";
|
|||
rel2 { to_x: "e.swallow.detail6"; offset: -1 -1; relative: 0.0 1.0; }
|
||||
}
|
||||
}
|
||||
part { name: "e.swallow.detail4"; type: SWALLOW; nomouse; scale;
|
||||
part { name: "e.swallow.detail4"; type: SWALLOW; scale;
|
||||
insert_after: "e.swallow.detail5";
|
||||
description { state: "default" 0.0; offscale;
|
||||
align: 1.0 0.5; min: 20 5;
|
||||
|
@ -1133,7 +1414,7 @@ group { name: "e/fileman/default/list/detailed";
|
|||
rel2 { to_x: "e.swallow.detail5"; offset: -1 -1; relative: 0.0 1.0; }
|
||||
}
|
||||
}
|
||||
part { name: "e.swallow.detail3"; type: SWALLOW; nomouse; scale;
|
||||
part { name: "e.swallow.detail3"; type: SWALLOW; scale;
|
||||
insert_after: "e.swallow.detail4";
|
||||
description { state: "default" 0.0; offscale;
|
||||
align: 1.0 0.5; min: 20 5;
|
||||
|
@ -1141,7 +1422,7 @@ group { name: "e/fileman/default/list/detailed";
|
|||
rel2 { to_x: "e.swallow.detail4"; offset: -1 -1; relative: 0.0 1.0; }
|
||||
}
|
||||
}
|
||||
part { name: "e.swallow.detail2"; type: SWALLOW; nomouse; scale;
|
||||
part { name: "e.swallow.detail2"; type: SWALLOW; scale;
|
||||
insert_after: "e.swallow.detail3";
|
||||
description { state: "default" 0.0; offscale;
|
||||
align: 1.0 0.5; min: 20 5;
|
||||
|
@ -1149,7 +1430,7 @@ group { name: "e/fileman/default/list/detailed";
|
|||
rel2 { to_x: "e.swallow.detail3"; offset: -1 -1; relative: 0.0 1.0; }
|
||||
}
|
||||
}
|
||||
part { name: "e.swallow.detail1"; type: SWALLOW; nomouse; scale;
|
||||
part { name: "e.swallow.detail1"; type: SWALLOW; scale;
|
||||
insert_after: "e.swallow.detail2";
|
||||
description { state: "default" 0.0; offscale;
|
||||
align: 1.0 0.5; min: 20 5;
|
||||
|
@ -1157,20 +1438,6 @@ group { name: "e/fileman/default/list/detailed";
|
|||
rel2 { to_x: "e.swallow.detail2"; offset: -1 -1; relative: 0.0 1.0; }
|
||||
}
|
||||
}
|
||||
part { name: "e.text.label";
|
||||
description { state: "default" 0.0;
|
||||
rel2.to_x: "e.swallow.detail1";
|
||||
rel2.relative: 0.0 1.0;
|
||||
}
|
||||
description { state: "selected" 0.0;
|
||||
rel2.to_x: "e.swallow.detail1";
|
||||
rel2.relative: 0.0 1.0;
|
||||
}
|
||||
description { state: "disabled" 0.0;
|
||||
rel2.to_x: "e.swallow.detail1";
|
||||
rel2.relative: 0.0 1.0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1306,6 +1573,21 @@ group { name: "e/fileman/default/icon/fixed";
|
|||
inherit: "default" 0.0;
|
||||
}
|
||||
}
|
||||
part { name: "icon_mono"; type: RECT;
|
||||
description { state: "default" 0.0;
|
||||
rel.to: "icon";
|
||||
color_class: "/fg/normal/grid/item";
|
||||
}
|
||||
description { state: "selected" 0.0;
|
||||
color_class: "/fg/selected/grid/item";
|
||||
}
|
||||
}
|
||||
part { name: "e.swallow.icon_mono"; type: SWALLOW; mouse_events: 0;
|
||||
clip_to: "icon_mono";
|
||||
description { state: "default" 0.0;
|
||||
rel.to: "icon0";
|
||||
}
|
||||
}
|
||||
part { name: "e.swallow.icon"; type: SWALLOW; mouse_events: 0;
|
||||
clip_to: "icon";
|
||||
description { state: "default" 0.0;
|
||||
|
@ -1451,11 +1733,13 @@ group { name: "e/fileman/default/icon/fixed";
|
|||
action: STATE_SET "selected" 0.0;
|
||||
target: "e.text.label";
|
||||
target: "base";
|
||||
target: "icon_mono";
|
||||
}
|
||||
program { signal: "e,state,unselected"; source: "e";
|
||||
action: STATE_SET "default" 0.0;
|
||||
target: "e.text.label";
|
||||
target: "base";
|
||||
target: "icon_mono";
|
||||
}
|
||||
program { signal: "mouse,down,1"; source: "label_event";
|
||||
script {
|
||||
|
|
|
@ -734,6 +734,9 @@ ICON("fprint", "i-fingerprint")
|
|||
|
||||
ICON("person-bust", "i-person-bust")
|
||||
|
||||
ICON("state-radio", "i-radio")
|
||||
ICON("state-check", "i-check")
|
||||
|
||||
#undef ICON
|
||||
|
||||
// regular icons
|
||||
|
@ -748,6 +751,7 @@ ICON("person-bust", "i-person-bust")
|
|||
} \
|
||||
} \
|
||||
}
|
||||
|
||||
ICON("folder", "i-folder")
|
||||
ICON("file", "i-file")
|
||||
ICON("clock", "i-clock")
|
||||
|
|
13
meson.build
13
meson.build
|
@ -118,6 +118,7 @@ if sys_windows
|
|||
error('Version of targetted Windows incorrect')
|
||||
endif
|
||||
add_project_arguments('-D__USE_MINGW_ANSI_STDIO', language: langs)
|
||||
add_global_arguments('-define:WIN32', language: 'cs')
|
||||
endif
|
||||
|
||||
if sys_sun
|
||||
|
@ -218,6 +219,10 @@ else
|
|||
error('System ' + host_machine.system() + ' not known')
|
||||
endif
|
||||
|
||||
if sys_linux or sys_bsd or sys_sun
|
||||
config_h.set('_STAT_VER_LINUX', '1')
|
||||
endif
|
||||
|
||||
if host_os == 'freebsd' or host_os == 'dragonfly'
|
||||
# This is necessary. We MUST use OpenSSL in base as bringing in from ports
|
||||
# can cause major issues (2 copies of the same library).
|
||||
|
@ -613,9 +618,11 @@ foreach evas_loader_map_inst : evas_loader_map
|
|||
meson.add_install_script('meson/evas_loader_conf.sh', evas_loader_original, evas_loader_link_types)
|
||||
endforeach
|
||||
|
||||
doxygen = find_program('doxygen', required : false)
|
||||
|
||||
if doxygen.found()
|
||||
doxygen = find_program('doxygen', required : get_option('docs'))
|
||||
if get_option('docs')
|
||||
if not doxygen.found()
|
||||
error('Need doxygen for docs')
|
||||
endif
|
||||
subdir('doc')
|
||||
endif
|
||||
|
||||
|
|
|
@ -382,3 +382,9 @@ option('max-fd-size',
|
|||
value : '8192',
|
||||
description : 'This is the maximim set of fds and thus maximum fd value allowed +1 in the ecore main loop handler'
|
||||
)
|
||||
|
||||
option('docs',
|
||||
type: 'boolean',
|
||||
value: false,
|
||||
description: 'Enable building C of documentation (Requires doxygen)'
|
||||
)
|
||||
|
|
|
@ -1 +1 @@
|
|||
ar az_IR ca cs da de el eo es fa fi fr gl he hu it ja ko_KR ko lt nl pl ps pt ru sl sr tr ur vi yi zh_CN
|
||||
ar az_IR ca cs da de el eo es fa fi fr gl he hu it ja ka ko_KR ko lt nl pl ps pt ru sl sr tr ur vi yi zh_CN
|
||||
|
|
|
@ -0,0 +1,276 @@
|
|||
# Georgian translation for Efl.
|
||||
# Copyright (C) 2022 Enlightenment development team
|
||||
# This file is put in the public domain.
|
||||
# Temuri Doghonadze <temuri.doghonadze@gmail.com>, 2022.
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: elementary 1.11\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2020-04-19 16:13+0200\n"
|
||||
"PO-Revision-Date: 2022-10-25 10:16+0200\n"
|
||||
"Last-Translator: Temuri Doghonadze <temuri.doghonadze@gmail.com>\n"
|
||||
"Language-Team: Georgian <(nothing)>\n"
|
||||
"Language: ka\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
|
||||
"X-Generator: Poedit 3.2\n"
|
||||
|
||||
#: src/lib/ecore/ecore_getopt.c:85
|
||||
msgid "Version:"
|
||||
msgstr "ვერსია:"
|
||||
|
||||
#: src/lib/ecore/ecore_getopt.c:94
|
||||
msgid "Usage:"
|
||||
msgstr "გამოყენება:"
|
||||
|
||||
#: src/lib/ecore/ecore_getopt.c:101
|
||||
#, c-format
|
||||
msgid "%s [options]"
|
||||
msgstr "%s [პარამეტრები]"
|
||||
|
||||
#: src/lib/ecore/ecore_getopt.c:301
|
||||
msgid "Copyright:"
|
||||
msgstr "უფლებები:"
|
||||
|
||||
#: src/lib/ecore/ecore_getopt.c:313
|
||||
msgid "License:"
|
||||
msgstr "ლიცენზია:"
|
||||
|
||||
#: src/lib/ecore/ecore_getopt.c:499
|
||||
msgid "Type: "
|
||||
msgstr "ტიპი: "
|
||||
|
||||
#: src/lib/ecore/ecore_getopt.c:575
|
||||
msgid "Default: "
|
||||
msgstr "ნაგულისხმები: "
|
||||
|
||||
#: src/lib/ecore/ecore_getopt.c:602
|
||||
msgid "Choices: "
|
||||
msgstr "არჩევანი: "
|
||||
|
||||
#: src/lib/ecore/ecore_getopt.c:640 src/lib/ecore/ecore_getopt.c:641
|
||||
msgid "No categories available."
|
||||
msgstr "კატეგორიები ხელმიუწვდომელია."
|
||||
|
||||
#: src/lib/ecore/ecore_getopt.c:645
|
||||
msgid "Categories: "
|
||||
msgstr "კატეგორიები: "
|
||||
|
||||
#: src/lib/ecore/ecore_getopt.c:767
|
||||
msgid "Options:\n"
|
||||
msgstr "პარამეტრები:\n"
|
||||
|
||||
#: src/lib/ecore/ecore_getopt.c:776
|
||||
msgid "Positional arguments:\n"
|
||||
msgstr "პოზიციური არგუმენტები:\n"
|
||||
|
||||
#: src/lib/ecore/ecore_getopt.c:843
|
||||
#, c-format
|
||||
msgid "ERROR: unknown category '%s'.\n"
|
||||
msgstr "შეცდომა: უცნობი კატეგორია '%s'.\n"
|
||||
|
||||
#: src/lib/ecore/ecore_getopt.c:947
|
||||
#, c-format
|
||||
msgid "ERROR: unknown option --%s.\n"
|
||||
msgstr "შეცდომა: უცნობი პარამეტრი --%s.\n"
|
||||
|
||||
#: src/lib/ecore/ecore_getopt.c:949
|
||||
#, c-format
|
||||
msgid "ERROR: unknown option -%c.\n"
|
||||
msgstr "შეცდომა: უცნობი პარამეტრი -%c.\n"
|
||||
|
||||
#: src/lib/ecore/ecore_getopt.c:1012
|
||||
msgid "ERROR: "
|
||||
msgstr "შეცდომა: "
|
||||
|
||||
#: src/lib/ecore/ecore_getopt.c:1108 src/lib/ecore/ecore_getopt.c:1245
|
||||
#: src/lib/ecore/ecore_getopt.c:1261 src/lib/ecore/ecore_getopt.c:1276
|
||||
#: src/lib/ecore/ecore_getopt.c:1296 src/lib/ecore/ecore_getopt.c:1343
|
||||
#: src/lib/ecore/ecore_getopt.c:1463 src/lib/ecore/ecore_getopt.c:1504
|
||||
msgid "value has no pointer set.\n"
|
||||
msgstr "მნიშვნელობას მაჩვენებელი დაყენებული არ აქვს.\n"
|
||||
|
||||
#: src/lib/ecore/ecore_getopt.c:1140 src/lib/ecore/ecore_getopt.c:1363
|
||||
#, c-format
|
||||
msgid "unknown boolean value %s.\n"
|
||||
msgstr "უცნობი ლოგიკური მნიშვნელობა %s.\n"
|
||||
|
||||
#: src/lib/ecore/ecore_getopt.c:1191 src/lib/ecore/ecore_getopt.c:1451
|
||||
#, c-format
|
||||
msgid "invalid number format %s\n"
|
||||
msgstr "რიცხვის არასწორი ფორმატი %s\n"
|
||||
|
||||
#: src/lib/ecore/ecore_getopt.c:1309
|
||||
#, c-format
|
||||
msgid "invalid choice \"%s\". Valid values are: "
|
||||
msgstr "არასწორი არჩევანი \"%s\". სწორი მნიშვნელობებია: "
|
||||
|
||||
#: src/lib/ecore/ecore_getopt.c:1337
|
||||
msgid "missing parameter to append.\n"
|
||||
msgstr "მისაწერი გამორჩენილი პარამეტრი.\n"
|
||||
|
||||
#: src/lib/ecore/ecore_getopt.c:1441
|
||||
msgid "could not parse value.\n"
|
||||
msgstr "მნიშვნელობის დამუშავების შეცდომა.\n"
|
||||
|
||||
#: src/lib/ecore/ecore_getopt.c:1498
|
||||
msgid "missing parameter.\n"
|
||||
msgstr "ნაკლული პარამეტრი.\n"
|
||||
|
||||
#: src/lib/ecore/ecore_getopt.c:1511
|
||||
msgid "missing callback function!\n"
|
||||
msgstr "ნაკლული უკუგამოძახების ფუნქცია!\n"
|
||||
|
||||
#: src/lib/ecore/ecore_getopt.c:1542
|
||||
msgid "no version was defined.\n"
|
||||
msgstr "ვერსია აღწერილი არაა.\n"
|
||||
|
||||
#: src/lib/ecore/ecore_getopt.c:1559
|
||||
msgid "no copyright was defined.\n"
|
||||
msgstr "საავტორო უფლებები აღწერილი არაა.\n"
|
||||
|
||||
#: src/lib/ecore/ecore_getopt.c:1576
|
||||
msgid "no license was defined.\n"
|
||||
msgstr "ლიცენზია აღწერილი არაა.\n"
|
||||
|
||||
#: src/lib/ecore/ecore_getopt.c:1666
|
||||
#, c-format
|
||||
msgid "ERROR: unknown option --%s, ignored.\n"
|
||||
msgstr "შეცდომა: უცნობი პარამეტრი --%s. იგნორირებულია.\n"
|
||||
|
||||
#: src/lib/ecore/ecore_getopt.c:1706
|
||||
#, c-format
|
||||
msgid "ERROR: option --%s requires an argument!\n"
|
||||
msgstr "შეცდომა: პარამეტრისთვის --%s არგუმენტი აუცილებელია!\n"
|
||||
|
||||
#: src/lib/ecore/ecore_getopt.c:1748
|
||||
#, c-format
|
||||
msgid "ERROR: unknown option -%c, ignored.\n"
|
||||
msgstr "შეცდომა: უცნობი პარამეტრი -%c, იგნორირებულია.\n"
|
||||
|
||||
#: src/lib/ecore/ecore_getopt.c:1793
|
||||
#, c-format
|
||||
msgid "ERROR: option -%c requires an argument!\n"
|
||||
msgstr "შეცდომა: პარამეტრისთვის -%c არგუმენტი აუცილებელია!\n"
|
||||
|
||||
#: src/lib/ecore/ecore_getopt.c:1888
|
||||
#, c-format
|
||||
msgid "ERROR: missing required positional argument %s.\n"
|
||||
msgstr "შეცდომა: ნაკლული აუცილებელი პოზიციური არგუმენტი %s.\n"
|
||||
|
||||
#: src/lib/ecore/ecore_getopt.c:1920
|
||||
#, c-format
|
||||
msgid "ERROR: unsupported action type %d for positional argument %s\n"
|
||||
msgstr ""
|
||||
"შეცდომა: ქმედების მხარდაუჭერელი ტიპი (%d) პოზიციური არგუმენტისთვის %s\n"
|
||||
|
||||
#: src/lib/ecore/ecore_getopt.c:2041 src/lib/ecore/ecore_getopt.c:2107
|
||||
msgid "ERROR: no parser provided.\n"
|
||||
msgstr "შეცდომა: დამმუშავებელი მოწოდებული არაა.\n"
|
||||
|
||||
#: src/lib/ecore/ecore_getopt.c:2046 src/lib/ecore/ecore_getopt.c:2112
|
||||
msgid "ERROR: no values provided.\n"
|
||||
msgstr "შეცდომა: მნიშვნელობები მითითებული არაა.\n"
|
||||
|
||||
#: src/lib/ecore/ecore_getopt.c:2055 src/lib/ecore/ecore_getopt.c:2121
|
||||
msgid "ERROR: no arguments provided.\n"
|
||||
msgstr "შეცდომა: არგუმენტები მითითებული არაა.\n"
|
||||
|
||||
#: src/lib/ecore/ecore_getopt.c:2081
|
||||
msgid "ERROR: invalid options found."
|
||||
msgstr "შეცდომა: აღმოჩენილია არასწორი პარამეტრები."
|
||||
|
||||
#: src/lib/ecore/ecore_getopt.c:2087 src/lib/ecore/ecore_getopt.c:2154
|
||||
#, c-format
|
||||
msgid " See --%s.\n"
|
||||
msgstr " იხილეთ --%s.\n"
|
||||
|
||||
#: src/lib/ecore/ecore_getopt.c:2089 src/lib/ecore/ecore_getopt.c:2156
|
||||
#, c-format
|
||||
msgid " See -%c.\n"
|
||||
msgstr " იხილეთ -%c.\n"
|
||||
|
||||
#: src/lib/ecore/ecore_getopt.c:2148
|
||||
msgid "ERROR: invalid positional arguments found."
|
||||
msgstr "შეცდომა: ნაპოვნია არასწორი პოზიციური არგუმენტები."
|
||||
|
||||
#: src/lib/ecore/ecore_getopt.c:2183
|
||||
#, c-format
|
||||
msgid "ERROR: incorrect geometry value '%s'\n"
|
||||
msgstr "შეცდომა: გეომეტრიის არასწორი მნიშვნელობა '%s'\n"
|
||||
|
||||
#: src/lib/ecore/ecore_getopt.c:2201
|
||||
#, c-format
|
||||
msgid "ERROR: incorrect size value '%s'\n"
|
||||
msgstr "შეცდომა: ზომის არასწორი მნიშვნელობა '%s'\n"
|
||||
|
||||
#: src/lib/efreet/efreet_base.c:127
|
||||
msgid "Desktop"
|
||||
msgstr "სამუშაო მაგიდა"
|
||||
|
||||
#: src/lib/efreet/efreet_base.c:135
|
||||
msgid "Downloads"
|
||||
msgstr "გადმოწერები"
|
||||
|
||||
#: src/lib/efreet/efreet_base.c:144
|
||||
msgid "Templates"
|
||||
msgstr "შაბლონები"
|
||||
|
||||
#: src/lib/efreet/efreet_base.c:153
|
||||
msgid "Public"
|
||||
msgstr "საჯარო"
|
||||
|
||||
#: src/lib/efreet/efreet_base.c:162
|
||||
msgid "Documents"
|
||||
msgstr "დოკუმენტები"
|
||||
|
||||
#: src/lib/efreet/efreet_base.c:170
|
||||
msgid "Music"
|
||||
msgstr "მუსიკა"
|
||||
|
||||
#: src/lib/efreet/efreet_base.c:178
|
||||
msgid "Pictures"
|
||||
msgstr "სურათები"
|
||||
|
||||
#: src/lib/efreet/efreet_base.c:186
|
||||
msgid "Videos"
|
||||
msgstr "ვიდეო"
|
||||
|
||||
#: src/lib/evas/common/language/evas_language_utils.c:205
|
||||
msgid "default:LTR"
|
||||
msgstr "default:LTR"
|
||||
|
||||
#: src/lib/elementary/elc_naviframe.c:408
|
||||
msgid "Title"
|
||||
msgstr "სათაური"
|
||||
|
||||
#: src/lib/elementary/elc_naviframe.c:415
|
||||
msgid "Subtitle"
|
||||
msgstr "სუბტიტრები"
|
||||
|
||||
#: src/lib/elementary/elc_naviframe.c:966
|
||||
msgid "Back"
|
||||
msgstr "უკან"
|
||||
|
||||
#: src/lib/elementary/elc_fileselector.c:1755
|
||||
msgid "Up"
|
||||
msgstr "მაღლა"
|
||||
|
||||
#: src/lib/elementary/elc_fileselector.c:1769
|
||||
msgid "Home"
|
||||
msgstr "საწყისი"
|
||||
|
||||
#: src/lib/elementary/elc_fileselector.c:1787
|
||||
msgid "Search"
|
||||
msgstr "ძებნა"
|
||||
|
||||
#: src/lib/elementary/elc_fileselector.c:2061
|
||||
msgid "OK"
|
||||
msgstr "დიახ"
|
||||
|
||||
#: src/lib/elementary/elc_fileselector.c:2070
|
||||
msgid "Cancel"
|
||||
msgstr "გაუქმება"
|
||||
|
38
po/pt.po
38
po/pt.po
|
@ -1,22 +1,23 @@
|
|||
# Portuguese translation for Efl.
|
||||
# Copyright (C) 2012 Enlightenment development team
|
||||
# This file is public domain.
|
||||
# Sérgio Marques <smarquespt@gmail.com>, 2010-2014
|
||||
# Sérgio Marques <smarquespt@gmail.com>, 2010-2014.
|
||||
# Hugo Carvalho <hugokarvalho@hotmail.com> 2021-2022.
|
||||
#
|
||||
#: src/lib/elementary/elm_config.c:4267
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: Elementary\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2020-04-19 16:13+0200\n"
|
||||
"PO-Revision-Date: 2013-11-05 14:11-0000\n"
|
||||
"Last-Translator: Sérgio Marques <smarquespt@gmail.com>\n"
|
||||
"Language-Team: General\n"
|
||||
"PO-Revision-Date: 2022-10-02 22:21+0100\n"
|
||||
"Last-Translator: Hugo Carvalho <hugokarvalho@hotmail.com>\n"
|
||||
"Language-Team: Hugo Carvalho <hugokarvalho@hotmail.com>\n"
|
||||
"Language: pt\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"X-Generator: Poedit 1.6.4\n"
|
||||
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
|
||||
"X-Generator: Poedit 3.1.1\n"
|
||||
"X-Launchpad-Export-Date: 2012-12-07 16:20+0000\n"
|
||||
|
||||
#: src/lib/ecore/ecore_getopt.c:85
|
||||
|
@ -30,7 +31,7 @@ msgstr "Utilização:"
|
|||
#: src/lib/ecore/ecore_getopt.c:101
|
||||
#, c-format
|
||||
msgid "%s [options]"
|
||||
msgstr "%s [opções]"
|
||||
msgstr "%s [options]"
|
||||
|
||||
#: src/lib/ecore/ecore_getopt.c:301
|
||||
msgid "Copyright:"
|
||||
|
@ -42,15 +43,15 @@ msgstr "Licença:"
|
|||
|
||||
#: src/lib/ecore/ecore_getopt.c:499
|
||||
msgid "Type: "
|
||||
msgstr "Tipo:"
|
||||
msgstr "Tipo: "
|
||||
|
||||
#: src/lib/ecore/ecore_getopt.c:575
|
||||
msgid "Default: "
|
||||
msgstr "Padrão:"
|
||||
msgstr "Padrão: "
|
||||
|
||||
#: src/lib/ecore/ecore_getopt.c:602
|
||||
msgid "Choices: "
|
||||
msgstr "Escolhas:"
|
||||
msgstr "Escolhas: "
|
||||
|
||||
#: src/lib/ecore/ecore_getopt.c:640 src/lib/ecore/ecore_getopt.c:641
|
||||
msgid "No categories available."
|
||||
|
@ -58,7 +59,7 @@ msgstr "Nenhuma categoria disponível."
|
|||
|
||||
#: src/lib/ecore/ecore_getopt.c:645
|
||||
msgid "Categories: "
|
||||
msgstr "Categorias:"
|
||||
msgstr "Categorias: "
|
||||
|
||||
#: src/lib/ecore/ecore_getopt.c:767
|
||||
msgid "Options:\n"
|
||||
|
@ -107,7 +108,7 @@ msgstr "formato numérico inválido %s\n"
|
|||
#: src/lib/ecore/ecore_getopt.c:1309
|
||||
#, c-format
|
||||
msgid "invalid choice \"%s\". Valid values are: "
|
||||
msgstr "escolha inválida \"%s\". O valores possíveis são:"
|
||||
msgstr "escolha inválida \"%s\". O valores possíveis são: "
|
||||
|
||||
#: src/lib/ecore/ecore_getopt.c:1337
|
||||
msgid "missing parameter to append.\n"
|
||||
|
@ -186,12 +187,12 @@ msgstr "ERRO: encontradas opções inválidas."
|
|||
#: src/lib/ecore/ecore_getopt.c:2087 src/lib/ecore/ecore_getopt.c:2154
|
||||
#, c-format
|
||||
msgid " See --%s.\n"
|
||||
msgstr "Consulte --%s.\n"
|
||||
msgstr " Veja --%s.\n"
|
||||
|
||||
#: src/lib/ecore/ecore_getopt.c:2089 src/lib/ecore/ecore_getopt.c:2156
|
||||
#, c-format
|
||||
msgid " See -%c.\n"
|
||||
msgstr "Consulte -%c.\n"
|
||||
msgstr " Veja -%c.\n"
|
||||
|
||||
#: src/lib/ecore/ecore_getopt.c:2148
|
||||
msgid "ERROR: invalid positional arguments found."
|
||||
|
@ -241,20 +242,19 @@ msgstr "Vídeos"
|
|||
|
||||
#: src/lib/evas/common/language/evas_language_utils.c:205
|
||||
msgid "default:LTR"
|
||||
msgstr "default:LTR"
|
||||
msgstr "padrão: LTR (da esquerda para a direita)"
|
||||
|
||||
#: src/lib/elementary/elc_naviframe.c:408
|
||||
msgid "Title"
|
||||
msgstr "Título"
|
||||
|
||||
#: src/lib/elementary/elc_naviframe.c:415
|
||||
#, fuzzy
|
||||
msgid "Subtitle"
|
||||
msgstr "Título"
|
||||
msgstr "Legenda"
|
||||
|
||||
#: src/lib/elementary/elc_naviframe.c:966
|
||||
msgid "Back"
|
||||
msgstr "Recuar"
|
||||
msgstr "Voltar"
|
||||
|
||||
#: src/lib/elementary/elc_fileselector.c:1755
|
||||
msgid "Up"
|
||||
|
@ -266,7 +266,7 @@ msgstr "Pasta pessoal"
|
|||
|
||||
#: src/lib/elementary/elc_fileselector.c:1787
|
||||
msgid "Search"
|
||||
msgstr ""
|
||||
msgstr "Procurar"
|
||||
|
||||
#: src/lib/elementary/elc_fileselector.c:2061
|
||||
msgid "OK"
|
||||
|
|
|
@ -43,9 +43,9 @@ if meson.is_cross_build()
|
|||
edje_depends = []
|
||||
else
|
||||
if sys_windows == true
|
||||
edje_cc_exe = [edje_cc.full_path()]
|
||||
edje_cc_exe = [edje_cc]
|
||||
else
|
||||
edje_cc_exe = [env, asan_option, 'EFL_RUN_IN_TREE=1', edje_cc.full_path()]
|
||||
edje_cc_exe = [env, asan_option, 'EFL_RUN_IN_TREE=1', edje_cc]
|
||||
endif
|
||||
edje_depends = [edje_cc, epp, evas_engine_buffer_mod, embryo_cc]
|
||||
endif
|
||||
|
@ -97,7 +97,7 @@ if meson.is_cross_build()
|
|||
edje_codegen_path = _edje_codegen.path()
|
||||
edje_codegen_exe = [_edje_codegen]
|
||||
else
|
||||
edje_codegen_exe = [env, asan_option, 'EFL_RUN_IN_TREE=1', edje_codegen.full_path()]
|
||||
edje_codegen_exe = [env, asan_option, 'EFL_RUN_IN_TREE=1', edje_codegen]
|
||||
endif
|
||||
|
||||
edje_pick = executable('edje_pick',
|
||||
|
|
|
@ -2029,7 +2029,7 @@ _status_config_etc(Evas_Object *win,
|
|||
elm_check_state_set(ck, elm_config_desktop_entry_get());
|
||||
|
||||
// desktop_entry
|
||||
CHECK_ADD("Entry Mangifiers", "Set popup magnifiers on start/end selection handles in entries", mag_change, NULL);
|
||||
CHECK_ADD("Entry Magnifiers", "Set popup magnifiers on start/end selection handles in entries", mag_change, NULL);
|
||||
elm_check_state_set(ck, elm_config_magnifier_enable_get());
|
||||
|
||||
// access
|
||||
|
@ -2455,7 +2455,8 @@ _status_config_icons(Evas_Object *win,
|
|||
ic = elm_icon_add(li);
|
||||
elm_image_file_set(ic, efreet_icon_path_find(th->name.internal, "folder", 48), NULL);
|
||||
list_it = elm_list_item_append(li, th->name.name, ic, NULL,
|
||||
_icon_theme_sel, th->name.internal);
|
||||
_icon_theme_sel,
|
||||
eina_stringshare_add(th->name.internal));
|
||||
|
||||
if (!strcmp(th->name.internal, "hicolor"))
|
||||
def_it = list_it;
|
||||
|
@ -4085,9 +4086,9 @@ _status_config_scrolling(Evas_Object *win,
|
|||
evas_object_smart_callback_add(sl, "delay,changed", smooth_win_change, NULL);
|
||||
|
||||
|
||||
evas_object_data_set(win, "scrolling", sc);
|
||||
evas_object_data_set(win, "scrolling", bx);
|
||||
|
||||
elm_naviframe_item_simple_push(naviframe, sc);
|
||||
elm_naviframe_item_simple_push(naviframe, bx);
|
||||
}
|
||||
|
||||
static void
|
||||
|
|
|
@ -36,7 +36,8 @@ _group_1_create(Evas_Object *bx, const char *style)
|
|||
|
||||
// radio 1
|
||||
ic = elm_icon_add(bx2);
|
||||
snprintf(buf, sizeof(buf), "%s/images/logo_small.png", elm_app_data_dir_get());
|
||||
elm_icon_standard_set(ic, "menu/folder");
|
||||
// snprintf(buf, sizeof(buf), "%s/images/logo_small.png", elm_app_data_dir_get());
|
||||
elm_image_file_set(ic, buf, NULL);
|
||||
evas_object_size_hint_aspect_set(ic, EVAS_ASPECT_CONTROL_VERTICAL, 1, 1);
|
||||
|
||||
|
@ -217,5 +218,14 @@ test_radio(void *data EINA_UNUSED, Evas_Object *obj EINA_UNUSED,
|
|||
_group_1_create(bx, "icon");
|
||||
_group_2_create(bx, "icon");
|
||||
|
||||
bx = elm_box_add(win);
|
||||
evas_object_size_hint_weight_set(bx, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
|
||||
elm_box_horizontal_set(bx, EINA_TRUE);
|
||||
elm_box_pack_end(bx0, bx);
|
||||
evas_object_show(bx);
|
||||
|
||||
_group_1_create(bx, "sort_header");
|
||||
_group_2_create(bx, "sort_header");
|
||||
|
||||
evas_object_show(win);
|
||||
}
|
||||
|
|
|
@ -14,17 +14,25 @@ map = run_command('map_generate.sh').stdout()
|
|||
|
||||
efl_libs = configuration_data()
|
||||
efl_libs.set('EFL_MONO_LIBRARY_MAP', map)
|
||||
efl_libs.set('CUSTOM_EXPORTS_MONO_DL_MONO', 'eflcustomexportsmono')
|
||||
efl_libs.set('EVIL_DL_MONO', 'dl')
|
||||
if sys_osx
|
||||
efl_libs.set('LIBDL_DL_MONO', 'dl.dylib')
|
||||
efl_libs.set('CUSTOM_EXPORTS_MONO_DL_MONO', 'eflcustomexportsmono')
|
||||
elif sys_windows
|
||||
efl_libs.set('LIBDL_DL_MONO', 'libdl.dll')
|
||||
efl_libs.set('CUSTOM_EXPORTS_MONO_DL_MONO', 'libeflcustomexportsmono' + '-' + version_major)
|
||||
else
|
||||
efl_libs.set('LIBDL_DL_MONO', 'libdl.so')
|
||||
efl_libs.set('CUSTOM_EXPORTS_MONO_DL_MONO', 'eflcustomexportsmono')
|
||||
endif
|
||||
|
||||
foreach mono_libs : mono_sublibs
|
||||
key = mono_libs[0].to_upper()+'_DL_MONO'
|
||||
efl_libs.set(key, mono_libs[0].to_lower())
|
||||
if target_machine.system() == 'windows'
|
||||
efl_libs.set(key, 'lib' + mono_libs[0].to_lower() + '-' + version_major)
|
||||
else
|
||||
efl_libs.set(key, mono_libs[0].to_lower())
|
||||
endif
|
||||
endforeach
|
||||
|
||||
configure_file(
|
||||
|
|
|
@ -17,12 +17,13 @@
|
|||
<!-- </PropertyGroup> -->
|
||||
<PropertyGroup>
|
||||
<DefineConstants>@EFL_BETA@</DefineConstants>
|
||||
<DefineConstants>@EFL_WIN32@</DefineConstants>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Compile Include="@BINDING_SRC@/efl_mono/*.cs" />
|
||||
<!-- FIXME Windows support -->
|
||||
<Compile Include="@BINDING_SRC@/eo_mono/*.cs" Exclude="@BINDING_SRC@/eo_mono/*Windows.cs" />
|
||||
<Compile Include="@BINDING_SRC@/eo_mono/*.cs" />
|
||||
<Compile Include="@BINDING_SRC@/eina_mono/*.cs" />
|
||||
<Compile Include="@BINDING_SRC@/eolian_mono/*.cs" />
|
||||
<Compile Include="@BINDING_SRC@/eldbus_mono/*.cs" />
|
||||
|
|
|
@ -13,6 +13,8 @@
|
|||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
#if !WIN32
|
||||
|
||||
using System;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
|
@ -40,3 +42,5 @@ internal static partial class FunctionInterop
|
|||
}
|
||||
|
||||
}
|
||||
|
||||
#endif
|
|
@ -13,19 +13,26 @@
|
|||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#if WIN32
|
||||
|
||||
using System;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace Efl.Eo
|
||||
{
|
||||
|
||||
static partial class FunctionInterop
|
||||
internal static partial class FunctionInterop
|
||||
{
|
||||
[DllImport(efl.Libs.Libdl)]
|
||||
[DllImport(efl.Libs.Kernel32, CharSet = CharSet.Ansi, ExactSpelling = true, SetLastError = true)]
|
||||
internal static extern IntPtr GetProcAddress(IntPtr handle, string symbol);
|
||||
|
||||
private static IntPtr LoadFunctionPointer(IntPtr nativeLibraryHandle, string functionName)
|
||||
=> FunctionInterop.GetProcAddress(nativeLibraryHandle, functionName);
|
||||
private static IntPtr dlsym(IntPtr handle, string symbol) => FunctionInterop.GetProcAddress(handle, symbol);
|
||||
|
||||
internal static IntPtr LoadFunctionPointer(IntPtr nativeLibraryHandle, string functionName) =>
|
||||
FunctionInterop.GetProcAddress(nativeLibraryHandle, functionName);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#endif
|
|
@ -13,6 +13,8 @@
|
|||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
#if !WIN32
|
||||
|
||||
using System;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
|
@ -98,3 +100,5 @@ internal partial class NativeModule
|
|||
}
|
||||
|
||||
}
|
||||
|
||||
#endif
|
|
@ -13,16 +13,32 @@
|
|||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
#if WIN32
|
||||
|
||||
using System;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace Efl.Eo
|
||||
{
|
||||
|
||||
internal class partial NativeModule
|
||||
internal partial class NativeModule
|
||||
{
|
||||
[DllImport(efl.Libs.Kernel32, CharSet = CharSet.Unicode, SetLastError = true)]
|
||||
internal static extern IntPtr LoadLibrary(string libFilename);
|
||||
[DllImport(efl.Libs.Kernel32, EntryPoint = "LoadLibrary", CharSet = CharSet.Unicode, SetLastError = true)]
|
||||
private static extern IntPtr _LoadLibrary(string libFilename);
|
||||
|
||||
internal static IntPtr LoadLibrary(string libFilename)
|
||||
{
|
||||
if (!libFilename.StartsWith("lib"))
|
||||
{
|
||||
libFilename = "lib" + libFilename + "-1";
|
||||
}
|
||||
return NativeModule._LoadLibrary(libFilename);
|
||||
}
|
||||
|
||||
[DllImport(efl.Libs.Kernel32, CharSet = CharSet.Unicode, SetLastError = true)]
|
||||
internal static extern void UnloadLibrary(IntPtr handle);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#endif
|
|
@ -81,7 +81,7 @@ internal static class Globals
|
|||
efl_ref(IntPtr eo);
|
||||
internal delegate void
|
||||
efl_unref_delegate(IntPtr eo);
|
||||
[DllImport(efl.Libs.CustomExports)] internal static extern void
|
||||
[DllImport(efl.Libs.Eo)] internal static extern void
|
||||
efl_unref(IntPtr eo);
|
||||
internal delegate int
|
||||
efl_ref_count_delegate(IntPtr eo);
|
||||
|
|
|
@ -4,11 +4,9 @@ mono_files += files(
|
|||
'FunctionWrapper.cs',
|
||||
'NativeModule.cs',
|
||||
'EoWrapper.cs',
|
||||
'WrapperSupervisor.cs'
|
||||
'WrapperSupervisor.cs',
|
||||
'FunctionWrapper_Windows.cs',
|
||||
'NativeModule_Windows.cs',
|
||||
'FunctionWrapper_Unix.cs',
|
||||
'NativeModule_Unix.cs'
|
||||
)
|
||||
|
||||
if host_machine.system() == 'windows'
|
||||
mono_files += files('FunctionWrapper_Windows.cs', 'NativeModule_Windows.cs')
|
||||
else
|
||||
mono_files += files('FunctionWrapper_Unix.cs', 'NativeModule_Unix.cs')
|
||||
endif
|
||||
|
|
|
@ -1,3 +1,7 @@
|
|||
cmake = import('cmake')
|
||||
opt_var = cmake.subproject_options()
|
||||
opt_var.set_override_option('cpp_std', 'c++17')
|
||||
|
||||
inc_dir = include_directories(join_paths('..', '..', '..', 'bin', 'eolian_mono'))
|
||||
|
||||
eolian_mono_gen_bin = executable('eolian_mono',
|
||||
|
|
|
@ -81,6 +81,11 @@ foreach lib : mono_sublibs
|
|||
package_name = lib[0].to_lower()
|
||||
eo_file_subdirs = get_variable(package_name + '_eo_subdirs')
|
||||
file_location = join_paths('..', '..', 'lib', package_name)
|
||||
dllimport = package_name
|
||||
|
||||
if target_machine.system() == 'windows'
|
||||
dllimport = 'lib' + dllimport + '-' + version_major
|
||||
endif
|
||||
|
||||
if (package_name != 'eldbus')
|
||||
foreach eo_file_subdir : eo_file_subdirs
|
||||
|
@ -101,7 +106,7 @@ foreach lib : mono_sublibs
|
|||
input : join_paths(subdir_file_location, mono_gen_file),
|
||||
output : [mono_gen_file + '.cs'],
|
||||
command : [eolian_mono_gen, beta_option, '-I', meson.current_source_dir(), eolian_include_directories,
|
||||
'--dllimport', package_name,
|
||||
'--dllimport', dllimport,
|
||||
'-o', join_paths(meson.current_build_dir(), mono_gen_file + '.cs'),
|
||||
'-e', get_option('mono-examples-dir'), partial,
|
||||
'@INPUT@'])
|
||||
|
@ -211,7 +216,22 @@ if (get_option('dotnet'))
|
|||
# The major version should be enough for now while we don't have to deal
|
||||
# with minor differences and dotnet core is far from version 10
|
||||
dotnet_major_version = dotnet_version.stdout().strip()[0].to_int()
|
||||
if dotnet_major_version == 3
|
||||
if dotnet_major_version == 8
|
||||
dotnet_core_app_version = '8.0'
|
||||
dotnet_standard_version = '2.1'
|
||||
elif dotnet_major_version == 7
|
||||
dotnet_core_app_version = '7.0'
|
||||
dotnet_standard_version = '2.1'
|
||||
elif dotnet_major_version == 6
|
||||
dotnet_core_app_version = '6.0'
|
||||
dotnet_standard_version = '2.1'
|
||||
elif dotnet_major_version == 5
|
||||
dotnet_core_app_version = '5.0'
|
||||
dotnet_standard_version = '2.1'
|
||||
elif dotnet_major_version == 4
|
||||
dotnet_core_app_version = '4.0'
|
||||
dotnet_standard_version = '2.1'
|
||||
elif dotnet_major_version == 3
|
||||
dotnet_core_app_version = '3.0'
|
||||
dotnet_standard_version = '2.1'
|
||||
elif dotnet_major_version == 2
|
||||
|
@ -232,6 +252,13 @@ if (get_option('dotnet'))
|
|||
lib_csproj_conf_data.set('EFL_BETA', '')
|
||||
endif
|
||||
|
||||
if target_machine.system() == 'windows'
|
||||
lib_csproj_conf_data.set('EFL_WIN32', 'WIN32')
|
||||
else
|
||||
lib_csproj_conf_data.set('EFL_WIN32', '')
|
||||
endif
|
||||
|
||||
|
||||
lib_csproj = configure_file(input: 'efl_sharp.csproj.in',
|
||||
output: 'efl_sharp.csproj',
|
||||
configuration: lib_csproj_conf_data)
|
||||
|
|
|
@ -1,3 +1,8 @@
|
|||
msgid ""
|
||||
msgstr ""
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: UTF-8\n"
|
||||
|
||||
msgid "LOADING"
|
||||
msgstr "Loading..."
|
||||
|
||||
|
|
|
@ -1,3 +1,8 @@
|
|||
msgid ""
|
||||
msgstr ""
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: UTF-8\n"
|
||||
|
||||
msgid "LOADING"
|
||||
msgstr "लोड हो रहा है..."
|
||||
|
||||
|
|
|
@ -33,6 +33,14 @@ struct _ecore_exe_dead_exe
|
|||
char *cmd;
|
||||
};
|
||||
|
||||
#ifdef _WIN32
|
||||
/*
|
||||
* this job is used to close child processes when parent one is closed
|
||||
* see https://stackoverflow.com/a/53214/688348
|
||||
*/
|
||||
HANDLE _ecore_exe_win32_job = NULL;
|
||||
#endif
|
||||
|
||||
EAPI int ECORE_EXE_EVENT_ADD = 0;
|
||||
EAPI int ECORE_EXE_EVENT_DEL = 0;
|
||||
EAPI int ECORE_EXE_EVENT_DATA = 0;
|
||||
|
@ -338,6 +346,21 @@ ecore_exe_hup(Ecore_Exe *obj)
|
|||
void
|
||||
_ecore_exe_init(void)
|
||||
{
|
||||
#ifdef _WIN32
|
||||
_ecore_exe_win32_job = CreateJobObject( NULL, NULL);
|
||||
if (_ecore_exe_win32_job)
|
||||
{
|
||||
JOBOBJECT_EXTENDED_LIMIT_INFORMATION jeli;
|
||||
|
||||
memset (&jeli, 0, sizeof(jeli));
|
||||
jeli.BasicLimitInformation.LimitFlags = JOB_OBJECT_LIMIT_KILL_ON_JOB_CLOSE;
|
||||
if (!SetInformationJobObject(_ecore_exe_win32_job, JobObjectExtendedLimitInformation, &jeli, sizeof(jeli)))
|
||||
{
|
||||
CloseHandle(_ecore_exe_win32_job);
|
||||
_ecore_exe_win32_job = NULL;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
ECORE_EXE_EVENT_ADD = ecore_event_type_new();
|
||||
ECORE_EXE_EVENT_DEL = ecore_event_type_new();
|
||||
ECORE_EXE_EVENT_DATA = ecore_event_type_new();
|
||||
|
@ -358,6 +381,11 @@ _ecore_exe_shutdown(void)
|
|||
ECORE_EXE_EVENT_DEL,
|
||||
ECORE_EXE_EVENT_DATA,
|
||||
ECORE_EXE_EVENT_ERROR);
|
||||
|
||||
#ifdef _WIN32
|
||||
if (_ecore_exe_win32_job)
|
||||
CloseHandle(_ecore_exe_win32_job);
|
||||
#endif
|
||||
}
|
||||
|
||||
Ecore_Exe *
|
||||
|
|
|
@ -133,6 +133,10 @@ struct _Ecore_Exe_Data
|
|||
|
||||
typedef struct _Ecore_Exe_Data Ecore_Exe_Data;
|
||||
|
||||
#ifdef _WIN32
|
||||
extern HANDLE _ecore_exe_win32_job;
|
||||
#endif
|
||||
|
||||
EAPI extern int ECORE_EXE_EVENT_ADD;
|
||||
EAPI extern int ECORE_EXE_EVENT_DEL;
|
||||
EAPI extern int ECORE_EXE_EVENT_DATA;
|
||||
|
|
|
@ -512,6 +512,13 @@ _impl_ecore_exe_efl_object_finalize(Eo *obj, Ecore_Exe_Data *exe)
|
|||
goto error;
|
||||
}
|
||||
|
||||
if ((flags & ECORE_EXE_TERM_WITH_PARENT) && _ecore_exe_win32_job)
|
||||
{
|
||||
if (!AssignProcessToJobObject(_ecore_exe_win32_job, pi.hProcess))
|
||||
WRN("AssignProcessToJobObject failed (job: %p, process: %p",
|
||||
_ecore_exe_win32_job, pi.hProcess);
|
||||
}
|
||||
|
||||
/*
|
||||
* Close pipe handles (do not continue to modify the parent).
|
||||
* We need to make sure that no handles to the write end of the
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -1,60 +1,49 @@
|
|||
#include "ecore_drm2_private.h"
|
||||
|
||||
/* local variables */
|
||||
static int _ecore_drm2_init_count = 0;
|
||||
static void *drm_lib = NULL;
|
||||
static void *_drm_lib = NULL;
|
||||
|
||||
/* external variables */
|
||||
int _ecore_drm2_log_dom = -1;
|
||||
|
||||
int (*sym_drmHandleEvent)(int fd, drmEventContext *evctx) = NULL;
|
||||
void *(*sym_drmGetVersion)(int fd) = NULL;
|
||||
void (*sym_drmFreeVersion)(void *drmver) = NULL;
|
||||
void *(*sym_drmModeGetProperty)(int fd, uint32_t propertyId) = NULL;
|
||||
void (*sym_drmModeFreeProperty)(drmModePropertyPtr ptr) = NULL;
|
||||
void *(*sym_drmModeGetPropertyBlob)(int fd, uint32_t blob_id) = NULL;
|
||||
void (*sym_drmModeFreePropertyBlob)(drmModePropertyBlobPtr ptr) = NULL;
|
||||
int (*sym_drmModeDestroyPropertyBlob)(int fd, uint32_t id) = NULL;
|
||||
int (*sym_drmIoctl)(int fd, unsigned long request, void *arg) = NULL;
|
||||
void *(*sym_drmModeObjectGetProperties)(int fd, uint32_t object_id, uint32_t object_type) = NULL;
|
||||
void (*sym_drmModeFreeObjectProperties)(drmModeObjectPropertiesPtr ptr) = NULL;
|
||||
int (*sym_drmModeCreatePropertyBlob)(int fd, const void *data, size_t size, uint32_t *id) = NULL;
|
||||
/* external drm function prototypes (for dlopen) */
|
||||
void *(*sym_drmModeGetResources)(int fd) = NULL;
|
||||
void (*sym_drmModeFreeResources)(drmModeResPtr ptr) = NULL;
|
||||
int (*sym_drmGetCap)(int fd, uint64_t capability, uint64_t *value);
|
||||
int (*sym_drmSetClientCap)(int fd, uint64_t capability, uint64_t value) = NULL;
|
||||
void *(*sym_drmModeGetProperty)(int fd, uint32_t propertyId);
|
||||
void (*sym_drmModeFreeProperty)(drmModePropertyPtr ptr);
|
||||
void *(*sym_drmModeGetPropertyBlob)(int fd, uint32_t blob_id);
|
||||
void (*sym_drmModeFreePropertyBlob)(drmModePropertyBlobPtr ptr);
|
||||
int (*sym_drmModeCreatePropertyBlob)(int fd, const void *data, size_t size, uint32_t *id);
|
||||
int (*sym_drmModeDestroyPropertyBlob)(int fd, uint32_t id);
|
||||
void *(*sym_drmModeObjectGetProperties)(int fd, uint32_t object_id, uint32_t object_type);
|
||||
void (*sym_drmModeFreeObjectProperties)(drmModeObjectPropertiesPtr ptr);
|
||||
void *(*sym_drmModeGetPlaneResources)(int fd);
|
||||
void (*sym_drmModeFreePlaneResources)(drmModePlaneResPtr ptr);
|
||||
void *(*sym_drmModeGetPlane)(int fd, uint32_t plane_id);
|
||||
void (*sym_drmModeFreePlane)(drmModePlanePtr ptr);
|
||||
void *(*sym_drmModeGetConnector)(int fd, uint32_t connectorId);
|
||||
void (*sym_drmModeFreeConnector)(drmModeConnectorPtr ptr);
|
||||
void *(*sym_drmModeGetEncoder)(int fd, uint32_t encoder_id);
|
||||
void (*sym_drmModeFreeEncoder)(drmModeEncoderPtr ptr);
|
||||
void *(*sym_drmModeGetCrtc)(int fd, uint32_t crtcId);
|
||||
void (*sym_drmModeFreeCrtc)(drmModeCrtcPtr ptr);
|
||||
void *(*sym_drmModeAtomicAlloc)(void) = NULL;
|
||||
void (*sym_drmModeAtomicFree)(drmModeAtomicReqPtr req) = NULL;
|
||||
int (*sym_drmModeAtomicAddProperty)(drmModeAtomicReqPtr req, uint32_t object_id, uint32_t property_id, uint64_t value) = NULL;
|
||||
int (*sym_drmModeAtomicCommit)(int fd, drmModeAtomicReqPtr req, uint32_t flags, void *user_data) = NULL;
|
||||
void (*sym_drmModeAtomicSetCursor)(drmModeAtomicReqPtr req, int cursor) = NULL;
|
||||
int (*sym_drmModeAtomicMerge)(drmModeAtomicReqPtr base, drmModeAtomicReqPtr augment);
|
||||
void *(*sym_drmModeGetEncoder)(int fd, uint32_t encoder_id) = NULL;
|
||||
void (*sym_drmModeFreeEncoder)(drmModeEncoderPtr ptr) = NULL;
|
||||
void *(*sym_drmModeGetCrtc)(int fd, uint32_t crtcId) = NULL;
|
||||
void (*sym_drmModeFreeCrtc)(drmModeCrtcPtr ptr) = NULL;
|
||||
int (*sym_drmModeSetCrtc)(int fd, uint32_t crtcId, uint32_t bufferId, uint32_t x, uint32_t y, uint32_t *connectors, int count, drmModeModeInfoPtr mode) = NULL;
|
||||
void *(*sym_drmModeGetResources)(int fd) = NULL;
|
||||
void (*sym_drmModeFreeResources)(drmModeResPtr ptr) = NULL;
|
||||
void *(*sym_drmModeGetConnector)(int fd, uint32_t connectorId) = NULL;
|
||||
void (*sym_drmModeFreeConnector)(drmModeConnectorPtr ptr) = NULL;
|
||||
int (*sym_drmModeConnectorSetProperty)(int fd, uint32_t connector_id, uint32_t property_id, uint64_t value) = NULL;
|
||||
int (*sym_drmGetCap)(int fd, uint64_t capability, uint64_t *value) = NULL;
|
||||
int (*sym_drmSetClientCap)(int fd, uint64_t capability, uint64_t value) = NULL;
|
||||
void *(*sym_drmModeGetPlaneResources)(int fd) = NULL;
|
||||
void (*sym_drmModeFreePlaneResources)(drmModePlaneResPtr ptr) = NULL;
|
||||
void *(*sym_drmModeGetPlane)(int fd, uint32_t plane_id) = NULL;
|
||||
void (*sym_drmModeFreePlane)(drmModePlanePtr ptr) = NULL;
|
||||
int (*sym_drmModeAddFB)(int fd, uint32_t width, uint32_t height, uint8_t depth, uint8_t bpp, uint32_t pitch, uint32_t bo_handle, uint32_t *buf_id) = NULL;
|
||||
int (*sym_drmModeAddFB2)(int fd, uint32_t width, uint32_t height, uint32_t pixel_format, uint32_t bo_handles[4], uint32_t pitches[4], uint32_t offsets[4], uint32_t *buf_id, uint32_t flags) = NULL;
|
||||
int (*sym_drmModeRmFB)(int fd, uint32_t bufferId) = NULL;
|
||||
int (*sym_drmModePageFlip)(int fd, uint32_t crtc_id, uint32_t fb_id, uint32_t flags, void *user_data) = NULL;
|
||||
int (*sym_drmModeDirtyFB)(int fd, uint32_t bufferId, drmModeClipPtr clips, uint32_t num_clips) = NULL;
|
||||
int (*sym_drmModeCrtcSetGamma)(int fd, uint32_t crtc_id, uint32_t size, uint16_t *red, uint16_t *green, uint16_t *blue) = NULL;
|
||||
int (*sym_drmPrimeFDToHandle)(int fd, int prime_fd, uint32_t *handle) = NULL;
|
||||
int (*sym_drmWaitVBlank)(int fd, drmVBlank *vbl) = NULL;
|
||||
|
||||
EAPI int ECORE_DRM2_EVENT_OUTPUT_CHANGED = -1;
|
||||
EAPI int ECORE_DRM2_EVENT_ACTIVATE = -1;
|
||||
|
||||
/* local static functions */
|
||||
static Eina_Bool
|
||||
_ecore_drm2_link(void)
|
||||
{
|
||||
int i, fail;
|
||||
int i;
|
||||
Eina_Bool fail = EINA_FALSE;
|
||||
const char *drm_libs[] =
|
||||
{
|
||||
"libdrm.so.2",
|
||||
|
@ -68,76 +57,62 @@ _ecore_drm2_link(void)
|
|||
do { \
|
||||
sym_ ## xx = dlsym(lib, #xx); \
|
||||
if (!(sym_ ## xx)) { \
|
||||
fail = 1; \
|
||||
fail = EINA_TRUE; \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
if (drm_lib) return EINA_TRUE;
|
||||
if (_drm_lib) return EINA_TRUE;
|
||||
|
||||
for (i = 0; drm_libs[i]; i++)
|
||||
{
|
||||
drm_lib = dlopen(drm_libs[i], RTLD_LOCAL | RTLD_LAZY);
|
||||
if (!drm_lib) continue;
|
||||
_drm_lib = dlopen(drm_libs[i], RTLD_LOCAL | RTLD_LAZY);
|
||||
if (!_drm_lib) continue;
|
||||
|
||||
fail = 0;
|
||||
fail = EINA_FALSE;
|
||||
|
||||
SYM(drm_lib, drmIoctl);
|
||||
/* SYM(drm_lib, drmClose); */
|
||||
SYM(drm_lib, drmWaitVBlank);
|
||||
SYM(drm_lib, drmHandleEvent);
|
||||
SYM(drm_lib, drmGetVersion);
|
||||
SYM(drm_lib, drmFreeVersion);
|
||||
SYM(drm_lib, drmModeGetProperty);
|
||||
SYM(drm_lib, drmModeFreeProperty);
|
||||
SYM(drm_lib, drmModeGetPropertyBlob);
|
||||
SYM(drm_lib, drmModeFreePropertyBlob);
|
||||
SYM(drm_lib, drmModeDestroyPropertyBlob);
|
||||
SYM(drm_lib, drmModeObjectGetProperties);
|
||||
SYM(drm_lib, drmModeFreeObjectProperties);
|
||||
SYM(drm_lib, drmModeCreatePropertyBlob);
|
||||
SYM(drm_lib, drmModeAtomicAlloc);
|
||||
SYM(drm_lib, drmModeAtomicFree);
|
||||
SYM(drm_lib, drmModeAtomicAddProperty);
|
||||
SYM(drm_lib, drmModeAtomicCommit);
|
||||
SYM(drm_lib, drmModeAtomicSetCursor);
|
||||
SYM(drm_lib, drmModeAtomicMerge);
|
||||
SYM(drm_lib, drmModeGetEncoder);
|
||||
SYM(drm_lib, drmModeFreeEncoder);
|
||||
SYM(drm_lib, drmModeGetCrtc);
|
||||
SYM(drm_lib, drmModeFreeCrtc);
|
||||
SYM(drm_lib, drmModeSetCrtc);
|
||||
SYM(drm_lib, drmModeGetResources);
|
||||
SYM(drm_lib, drmModeFreeResources);
|
||||
SYM(drm_lib, drmModeGetConnector);
|
||||
SYM(drm_lib, drmModeFreeConnector);
|
||||
SYM(drm_lib, drmModeConnectorSetProperty);
|
||||
SYM(drm_lib, drmGetCap);
|
||||
SYM(drm_lib, drmSetClientCap);
|
||||
SYM(drm_lib, drmModeGetPlaneResources);
|
||||
SYM(drm_lib, drmModeFreePlaneResources);
|
||||
SYM(drm_lib, drmModeGetPlane);
|
||||
SYM(drm_lib, drmModeFreePlane);
|
||||
SYM(drm_lib, drmModeAddFB);
|
||||
SYM(drm_lib, drmModeAddFB2);
|
||||
SYM(drm_lib, drmModeRmFB);
|
||||
SYM(drm_lib, drmModePageFlip);
|
||||
SYM(drm_lib, drmModeDirtyFB);
|
||||
SYM(drm_lib, drmModeCrtcSetGamma);
|
||||
SYM(drm_lib, drmPrimeFDToHandle);
|
||||
/* TODO: Sym needed libdrm functions */
|
||||
SYM(_drm_lib, drmModeGetResources);
|
||||
SYM(_drm_lib, drmModeFreeResources);
|
||||
SYM(_drm_lib, drmGetCap);
|
||||
SYM(_drm_lib, drmSetClientCap);
|
||||
SYM(_drm_lib, drmModeGetProperty);
|
||||
SYM(_drm_lib, drmModeFreeProperty);
|
||||
SYM(_drm_lib, drmModeGetPropertyBlob);
|
||||
SYM(_drm_lib, drmModeFreePropertyBlob);
|
||||
SYM(_drm_lib, drmModeCreatePropertyBlob);
|
||||
SYM(_drm_lib, drmModeDestroyPropertyBlob);
|
||||
SYM(_drm_lib, drmModeObjectGetProperties);
|
||||
SYM(_drm_lib, drmModeFreeObjectProperties);
|
||||
SYM(_drm_lib, drmModeGetPlaneResources);
|
||||
SYM(_drm_lib, drmModeFreePlaneResources);
|
||||
SYM(_drm_lib, drmModeGetPlane);
|
||||
SYM(_drm_lib, drmModeFreePlane);
|
||||
SYM(_drm_lib, drmModeGetConnector);
|
||||
SYM(_drm_lib, drmModeFreeConnector);
|
||||
SYM(_drm_lib, drmModeGetEncoder);
|
||||
SYM(_drm_lib, drmModeFreeEncoder);
|
||||
SYM(_drm_lib, drmModeGetCrtc);
|
||||
SYM(_drm_lib, drmModeFreeCrtc);
|
||||
SYM(_drm_lib, drmModeAtomicAlloc);
|
||||
SYM(_drm_lib, drmModeAtomicFree);
|
||||
SYM(_drm_lib, drmModeAtomicAddProperty);
|
||||
SYM(_drm_lib, drmModeAtomicCommit);
|
||||
SYM(_drm_lib, drmModeAtomicSetCursor);
|
||||
|
||||
if (fail)
|
||||
{
|
||||
dlclose(drm_lib);
|
||||
drm_lib = NULL;
|
||||
dlclose(_drm_lib);
|
||||
_drm_lib = NULL;
|
||||
}
|
||||
else
|
||||
break;
|
||||
}
|
||||
|
||||
if (!drm_lib) return EINA_FALSE;
|
||||
if (!_drm_lib) return EINA_FALSE;
|
||||
return EINA_TRUE;
|
||||
}
|
||||
|
||||
/* API functions */
|
||||
EAPI int
|
||||
ecore_drm2_init(void)
|
||||
{
|
||||
|
@ -171,7 +146,6 @@ ecore_drm2_init(void)
|
|||
goto log_err;
|
||||
}
|
||||
|
||||
ECORE_DRM2_EVENT_OUTPUT_CHANGED = ecore_event_type_new();
|
||||
ECORE_DRM2_EVENT_ACTIVATE = ecore_event_type_new();
|
||||
|
||||
if (!_ecore_drm2_link()) goto link_err;
|
||||
|
@ -204,7 +178,8 @@ ecore_drm2_shutdown(void)
|
|||
|
||||
if (--_ecore_drm2_init_count != 0) return _ecore_drm2_init_count;
|
||||
|
||||
ECORE_DRM2_EVENT_OUTPUT_CHANGED = -1;
|
||||
if (_drm_lib) dlclose(_drm_lib);
|
||||
|
||||
ECORE_DRM2_EVENT_ACTIVATE = -1;
|
||||
|
||||
eina_log_domain_unregister(_ecore_drm2_log_dom);
|
||||
|
@ -217,18 +192,3 @@ ecore_drm2_shutdown(void)
|
|||
|
||||
return _ecore_drm2_init_count;
|
||||
}
|
||||
|
||||
EAPI int
|
||||
ecore_drm2_event_handle(Ecore_Drm2_Device *dev, Ecore_Drm2_Context *drmctx)
|
||||
{
|
||||
drmEventContext ctx;
|
||||
|
||||
EINA_SAFETY_ON_NULL_RETURN_VAL(dev, -1);
|
||||
|
||||
memset(&ctx, 0, sizeof(ctx));
|
||||
ctx.version = 2;
|
||||
ctx.page_flip_handler = drmctx->page_flip_handler;
|
||||
ctx.vblank_handler = drmctx->vblank_handler;
|
||||
|
||||
return sym_drmHandleEvent(dev->fd, &ctx);
|
||||
}
|
||||
|
|
|
@ -0,0 +1,273 @@
|
|||
#include "ecore_drm2_private.h"
|
||||
|
||||
#ifndef DRM_MODE_CONNECTOR_WRITEBACK
|
||||
# define DRM_MODE_CONNECTOR_WRITEBACK 18
|
||||
#endif
|
||||
|
||||
static Eina_Thread_Queue *thq = NULL;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
Eina_Thread_Queue_Msg head;
|
||||
Ecore_Drm2_Thread_Op_Code code;
|
||||
} Thread_Msg;
|
||||
|
||||
static void
|
||||
_ecore_drm2_connector_state_thread_send(Ecore_Drm2_Thread_Op_Code code)
|
||||
{
|
||||
Thread_Msg *msg;
|
||||
void *ref;
|
||||
|
||||
msg = eina_thread_queue_send(thq, sizeof(Thread_Msg), &ref);
|
||||
msg->code = code;
|
||||
eina_thread_queue_send_done(thq, ref);
|
||||
}
|
||||
|
||||
static void
|
||||
_ecore_drm2_connector_state_debug(Ecore_Drm2_Connector *conn)
|
||||
{
|
||||
DBG("Connector Atomic State Fill Complete");
|
||||
DBG("\tConnector: %d", conn->state.current->obj_id);
|
||||
DBG("\t\tCrtc Id: %lu", (long)conn->state.current->crtc.value);
|
||||
DBG("\t\tDPMS: %lu", (long)conn->state.current->dpms.value);
|
||||
DBG("\t\tAspect Ratio: %lu", (long)conn->state.current->aspect.value);
|
||||
DBG("\t\tScaling Mode: %lu", (long)conn->state.current->scaling.value);
|
||||
}
|
||||
|
||||
static void
|
||||
_ecore_drm2_connector_state_fill(Ecore_Drm2_Connector *conn)
|
||||
{
|
||||
Ecore_Drm2_Connector_State *cstate;
|
||||
drmModeObjectPropertiesPtr oprops;
|
||||
unsigned int i = 0;
|
||||
|
||||
/* try to allocate space for connector Atomic state */
|
||||
conn->state.current = calloc(1, sizeof(Ecore_Drm2_Connector_State));
|
||||
if (!conn->state.current)
|
||||
{
|
||||
ERR("Could not allocate space for Connector state");
|
||||
return;
|
||||
}
|
||||
|
||||
cstate = conn->state.current;
|
||||
cstate->obj_id = conn->id;
|
||||
|
||||
/* get the properties of this connector from drm */
|
||||
oprops =
|
||||
sym_drmModeObjectGetProperties(conn->fd, cstate->obj_id,
|
||||
DRM_MODE_OBJECT_CONNECTOR);
|
||||
if (!oprops)
|
||||
{
|
||||
free(conn->state.current);
|
||||
return;
|
||||
}
|
||||
|
||||
for (; i < oprops->count_props; i++)
|
||||
{
|
||||
drmModePropertyPtr prop;
|
||||
|
||||
/* try to get this individual property */
|
||||
prop = sym_drmModeGetProperty(conn->fd, oprops->props[i]);
|
||||
if (!prop) continue;
|
||||
|
||||
/* check for the properties we are interested in */
|
||||
if (!strcmp(prop->name, "CRTC_ID"))
|
||||
{
|
||||
cstate->crtc.id = prop->prop_id;
|
||||
cstate->crtc.flags = prop->flags;
|
||||
cstate->crtc.value = oprops->prop_values[i];
|
||||
}
|
||||
else if (!strcmp(prop->name, "DPMS"))
|
||||
{
|
||||
cstate->dpms.id = prop->prop_id;
|
||||
cstate->dpms.flags = prop->flags;
|
||||
cstate->dpms.value = oprops->prop_values[i];
|
||||
}
|
||||
else if (!strcmp(prop->name, "EDID"))
|
||||
{
|
||||
drmModePropertyBlobPtr bp;
|
||||
|
||||
cstate->edid.id = oprops->prop_values[i];
|
||||
if (!cstate->edid.id)
|
||||
{
|
||||
cstate->edid.len = 0;
|
||||
goto cont;
|
||||
}
|
||||
|
||||
bp = sym_drmModeGetPropertyBlob(conn->fd, cstate->edid.id);
|
||||
if (!bp) goto cont;
|
||||
|
||||
if ((!cstate->edid.data) ||
|
||||
memcmp(cstate->edid.data, bp->data, bp->length) != 0)
|
||||
{
|
||||
cstate->edid.data = eina_memdup(bp->data, bp->length, 1);
|
||||
}
|
||||
|
||||
cstate->edid.len = bp->length;
|
||||
|
||||
if (cstate->edid.id != 0)
|
||||
sym_drmModeCreatePropertyBlob(conn->fd, bp->data, bp->length,
|
||||
&cstate->edid.id);
|
||||
|
||||
sym_drmModeFreePropertyBlob(bp);
|
||||
}
|
||||
else if (!strcmp(prop->name, "aspect ratio"))
|
||||
{
|
||||
cstate->aspect.id = prop->prop_id;
|
||||
cstate->aspect.flags = prop->flags;
|
||||
cstate->aspect.value = oprops->prop_values[i];
|
||||
}
|
||||
else if (!strcmp(prop->name, "scaling mode"))
|
||||
{
|
||||
cstate->scaling.id = prop->prop_id;
|
||||
cstate->scaling.flags = prop->flags;
|
||||
cstate->scaling.value = oprops->prop_values[i];
|
||||
}
|
||||
|
||||
cont:
|
||||
sym_drmModeFreeProperty(prop);
|
||||
}
|
||||
|
||||
sym_drmModeFreeObjectProperties(oprops);
|
||||
|
||||
/* duplicate current state into pending so we can handle changes */
|
||||
conn->state.pending = calloc(1, sizeof(Ecore_Drm2_Connector_State));
|
||||
if (conn->state.pending)
|
||||
memcpy(conn->state.pending, conn->state.current, sizeof(Ecore_Drm2_Connector_State));
|
||||
|
||||
/* send message to thread for debug printing connector state */
|
||||
_ecore_drm2_connector_state_thread_send(ECORE_DRM2_THREAD_CODE_DEBUG);
|
||||
}
|
||||
|
||||
static void
|
||||
_ecore_drm2_connector_state_thread(void *data, Ecore_Thread *thread)
|
||||
{
|
||||
Ecore_Drm2_Connector *conn;
|
||||
Thread_Msg *msg;
|
||||
void *ref;
|
||||
|
||||
conn = data;
|
||||
|
||||
eina_thread_name_set(eina_thread_self(), "Ecore-drm2-connector");
|
||||
|
||||
while (!ecore_thread_check(thread))
|
||||
{
|
||||
msg = eina_thread_queue_wait(thq, &ref);
|
||||
if (msg)
|
||||
{
|
||||
switch (msg->code)
|
||||
{
|
||||
case ECORE_DRM2_THREAD_CODE_FILL:
|
||||
_ecore_drm2_connector_state_fill(conn);
|
||||
break;
|
||||
case ECORE_DRM2_THREAD_CODE_DEBUG:
|
||||
_ecore_drm2_connector_state_debug(conn);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
eina_thread_queue_wait_done(thq, ref);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
_ecore_drm2_connector_state_thread_notify(void *data EINA_UNUSED, Ecore_Thread *thread EINA_UNUSED, void *msg)
|
||||
{
|
||||
free(msg);
|
||||
}
|
||||
|
||||
static Ecore_Drm2_Connector *
|
||||
_ecore_drm2_connector_create(Ecore_Drm2_Device *dev, drmModeConnector *conn, uint32_t id)
|
||||
{
|
||||
Ecore_Drm2_Connector *c;
|
||||
|
||||
/* try to allocate space for new connector */
|
||||
c = calloc(1, sizeof(Ecore_Drm2_Connector));
|
||||
if (!c) return NULL;
|
||||
|
||||
c->id = id;
|
||||
c->fd = dev->fd;
|
||||
c->drmConn = conn;
|
||||
c->type = conn->connector_type;
|
||||
|
||||
/* check if this connector is a writeback */
|
||||
if (conn->connector_type == DRM_MODE_CONNECTOR_WRITEBACK)
|
||||
c->writeback = EINA_TRUE;
|
||||
|
||||
/* append this connector to list */
|
||||
dev->conns = eina_list_append(dev->conns, c);
|
||||
|
||||
return c;
|
||||
}
|
||||
|
||||
Eina_Bool
|
||||
_ecore_drm2_connectors_create(Ecore_Drm2_Device *dev)
|
||||
{
|
||||
Ecore_Drm2_Connector *c;
|
||||
drmModeConnector *conn;
|
||||
drmModeRes *res;
|
||||
int i = 0;
|
||||
|
||||
/* try to get drm resources */
|
||||
res = sym_drmModeGetResources(dev->fd);
|
||||
if (!res) return EINA_FALSE;
|
||||
|
||||
/* TOOD: set dev->min/max width & height ? */
|
||||
|
||||
thq = eina_thread_queue_new();
|
||||
|
||||
for (; i < res->count_connectors; i++)
|
||||
{
|
||||
uint32_t conn_id;
|
||||
|
||||
conn_id = res->connectors[i];
|
||||
|
||||
/* try to get this connector from drm */
|
||||
conn = sym_drmModeGetConnector(dev->fd, conn_id);
|
||||
if (!conn) continue;
|
||||
|
||||
/* try to create a new connector */
|
||||
c = _ecore_drm2_connector_create(dev, conn, conn_id);
|
||||
if (!c) goto err;
|
||||
|
||||
/* NB: Use an explicit thread to fill crtc atomic state */
|
||||
c->thread =
|
||||
ecore_thread_feedback_run(_ecore_drm2_connector_state_thread,
|
||||
_ecore_drm2_connector_state_thread_notify,
|
||||
NULL, NULL, c, EINA_TRUE);
|
||||
|
||||
}
|
||||
|
||||
sym_drmModeFreeResources(res);
|
||||
return EINA_TRUE;
|
||||
|
||||
err:
|
||||
eina_thread_queue_free(thq);
|
||||
thq = NULL;
|
||||
_ecore_drm2_connectors_destroy(dev);
|
||||
sym_drmModeFreeConnector(conn);
|
||||
sym_drmModeFreeResources(res);
|
||||
return EINA_FALSE;
|
||||
}
|
||||
|
||||
void
|
||||
_ecore_drm2_connectors_destroy(Ecore_Drm2_Device *dev)
|
||||
{
|
||||
Ecore_Drm2_Connector *conn;
|
||||
|
||||
EINA_LIST_FREE(dev->conns, conn)
|
||||
{
|
||||
if (conn->thread) ecore_thread_cancel(conn->thread);
|
||||
if (conn->drmConn) sym_drmModeFreeConnector(conn->drmConn);
|
||||
free(conn->state.pending);
|
||||
free(conn->state.current);
|
||||
free(conn);
|
||||
}
|
||||
|
||||
if (thq)
|
||||
{
|
||||
eina_thread_queue_free(thq);
|
||||
thq = NULL;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,254 @@
|
|||
#include "ecore_drm2_private.h"
|
||||
|
||||
static Eina_Thread_Queue *thq = NULL;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
Eina_Thread_Queue_Msg head;
|
||||
Ecore_Drm2_Thread_Op_Code code;
|
||||
} Thread_Msg;
|
||||
|
||||
static void
|
||||
_ecore_drm2_crtc_state_thread_send(Ecore_Drm2_Thread_Op_Code code)
|
||||
{
|
||||
Thread_Msg *msg;
|
||||
void *ref;
|
||||
|
||||
msg = eina_thread_queue_send(thq, sizeof(Thread_Msg), &ref);
|
||||
msg->code = code;
|
||||
eina_thread_queue_send_done(thq, ref);
|
||||
}
|
||||
|
||||
static void
|
||||
_ecore_drm2_crtc_state_debug(Ecore_Drm2_Crtc *crtc)
|
||||
{
|
||||
DBG("CRTC Atomic State Fill Complete");
|
||||
DBG("\tCrtc: %d", crtc->state.current->obj_id);
|
||||
DBG("\t\tMode: %d", crtc->state.current->mode.value);
|
||||
DBG("\t\tActive: %lu", (long)crtc->state.current->active.value);
|
||||
}
|
||||
|
||||
static void
|
||||
_ecore_drm2_crtc_state_fill(Ecore_Drm2_Crtc *crtc)
|
||||
{
|
||||
Ecore_Drm2_Crtc_State *cstate;
|
||||
drmModeObjectPropertiesPtr oprops;
|
||||
unsigned int i = 0;
|
||||
|
||||
/* try to allocate space for current CRTC Atomic state */
|
||||
crtc->state.current = calloc(1, sizeof(Ecore_Drm2_Crtc_State));
|
||||
if (!crtc->state.current)
|
||||
{
|
||||
ERR("Could not allocate space for CRTC state");
|
||||
return;
|
||||
}
|
||||
|
||||
cstate = crtc->state.current;
|
||||
cstate->obj_id = crtc->drmCrtc->crtc_id;
|
||||
|
||||
/* get the properties of this crtc from drm */
|
||||
oprops =
|
||||
sym_drmModeObjectGetProperties(crtc->fd, cstate->obj_id,
|
||||
DRM_MODE_OBJECT_CRTC);
|
||||
if (!oprops)
|
||||
{
|
||||
free(crtc->state.current);
|
||||
return;
|
||||
}
|
||||
|
||||
for (; i < oprops->count_props; i++)
|
||||
{
|
||||
drmModePropertyPtr prop;
|
||||
|
||||
/* try to get this individual property */
|
||||
prop = sym_drmModeGetProperty(crtc->fd, oprops->props[i]);
|
||||
if (!prop) continue;
|
||||
|
||||
/* check for the properties we are interested in */
|
||||
if (!strcmp(prop->name, "MODE_ID"))
|
||||
{
|
||||
drmModePropertyBlobPtr bp;
|
||||
|
||||
cstate->mode.id = prop->prop_id;
|
||||
cstate->mode.value = oprops->prop_values[i];
|
||||
|
||||
if (!cstate->mode.value)
|
||||
{
|
||||
cstate->mode.len = 0;
|
||||
goto cont;
|
||||
}
|
||||
|
||||
bp = sym_drmModeGetPropertyBlob(crtc->fd, cstate->mode.value);
|
||||
if (!bp) goto cont;
|
||||
|
||||
if ((!cstate->mode.data) ||
|
||||
memcmp(cstate->mode.data, bp->data, bp->length) != 0)
|
||||
{
|
||||
cstate->mode.data = eina_memdup(bp->data, bp->length, 1);
|
||||
}
|
||||
|
||||
cstate->mode.len = bp->length;
|
||||
|
||||
if (cstate->mode.value != 0)
|
||||
sym_drmModeCreatePropertyBlob(crtc->fd, bp->data, bp->length,
|
||||
&cstate->mode.value);
|
||||
|
||||
sym_drmModeFreePropertyBlob(bp);
|
||||
}
|
||||
else if (!strcmp(prop->name, "ACTIVE"))
|
||||
{
|
||||
cstate->active.id = prop->prop_id;
|
||||
cstate->active.flags = prop->flags;
|
||||
cstate->active.value = oprops->prop_values[i];
|
||||
}
|
||||
/* TODO: We don't actually use this value yet */
|
||||
/* else if (!strcmp(prop->name, "BACKGROUND_COLOR")) */
|
||||
/* { */
|
||||
/* cstate->background.id = prop->prop_id; */
|
||||
/* cstate->background.flags = prop->flags; */
|
||||
/* cstate->background.value = oprops->prop_values[i]; */
|
||||
/* } */
|
||||
|
||||
cont:
|
||||
sym_drmModeFreeProperty(prop);
|
||||
}
|
||||
|
||||
sym_drmModeFreeObjectProperties(oprops);
|
||||
|
||||
/* duplicate current state into pending so we can handle changes */
|
||||
crtc->state.pending = calloc(1, sizeof(Ecore_Drm2_Crtc_State));
|
||||
if (crtc->state.pending)
|
||||
memcpy(crtc->state.pending, crtc->state.current, sizeof(Ecore_Drm2_Crtc_State));
|
||||
|
||||
/* send message to thread for debug printing crtc state */
|
||||
_ecore_drm2_crtc_state_thread_send(ECORE_DRM2_THREAD_CODE_DEBUG);
|
||||
}
|
||||
|
||||
static void
|
||||
_ecore_drm2_crtc_state_thread(void *data, Ecore_Thread *thread)
|
||||
{
|
||||
Ecore_Drm2_Crtc *crtc;
|
||||
Thread_Msg *msg;
|
||||
void *ref;
|
||||
|
||||
crtc = data;
|
||||
|
||||
eina_thread_name_set(eina_thread_self(), "Ecore-drm2-crtc");
|
||||
|
||||
while (!ecore_thread_check(thread))
|
||||
{
|
||||
msg = eina_thread_queue_wait(thq, &ref);
|
||||
if (msg)
|
||||
{
|
||||
switch (msg->code)
|
||||
{
|
||||
case ECORE_DRM2_THREAD_CODE_FILL:
|
||||
_ecore_drm2_crtc_state_fill(crtc);
|
||||
break;
|
||||
case ECORE_DRM2_THREAD_CODE_DEBUG:
|
||||
_ecore_drm2_crtc_state_debug(crtc);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
eina_thread_queue_wait_done(thq, ref);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
_ecore_drm2_crtc_state_thread_notify(void *data EINA_UNUSED, Ecore_Thread *thread EINA_UNUSED, void *msg)
|
||||
{
|
||||
/* Ecore_Drm2_Crtc *crtc; */
|
||||
|
||||
/* crtc = data; */
|
||||
|
||||
free(msg);
|
||||
}
|
||||
|
||||
static Ecore_Drm2_Crtc *
|
||||
_ecore_drm2_crtc_create(Ecore_Drm2_Device *dev, drmModeCrtcPtr dcrtc, uint32_t pipe)
|
||||
{
|
||||
Ecore_Drm2_Crtc *crtc;
|
||||
|
||||
/* try to allocate space for a crtc */
|
||||
crtc = calloc(1, sizeof(Ecore_Drm2_Crtc));
|
||||
if (!crtc)
|
||||
{
|
||||
ERR("Could not allocate space for CRTC");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
crtc->id = dcrtc->crtc_id;
|
||||
crtc->fd = dev->fd;
|
||||
crtc->pipe = pipe;
|
||||
crtc->drmCrtc = dcrtc;
|
||||
|
||||
/* add this crtc to the list */
|
||||
dev->crtcs = eina_list_append(dev->crtcs, crtc);
|
||||
|
||||
return crtc;
|
||||
}
|
||||
|
||||
Eina_Bool
|
||||
_ecore_drm2_crtcs_create(Ecore_Drm2_Device *dev)
|
||||
{
|
||||
Ecore_Drm2_Crtc *crtc;
|
||||
drmModeCrtcPtr c;
|
||||
drmModeRes *res;
|
||||
int i = 0;
|
||||
|
||||
/* try to get drm resources */
|
||||
res = sym_drmModeGetResources(dev->fd);
|
||||
if (!res) return EINA_FALSE;
|
||||
|
||||
thq = eina_thread_queue_new();
|
||||
|
||||
for (; i < res->count_crtcs; i++)
|
||||
{
|
||||
/* try to get this crtc from drm */
|
||||
c = sym_drmModeGetCrtc(dev->fd, res->crtcs[i]);
|
||||
|
||||
/* try to create a crtc */
|
||||
crtc = _ecore_drm2_crtc_create(dev, c, i);
|
||||
if (!crtc) goto err;
|
||||
|
||||
/* NB: Use an explicit thread to fill crtc atomic state */
|
||||
crtc->thread =
|
||||
ecore_thread_feedback_run(_ecore_drm2_crtc_state_thread,
|
||||
_ecore_drm2_crtc_state_thread_notify,
|
||||
NULL, NULL, crtc, EINA_TRUE);
|
||||
}
|
||||
|
||||
sym_drmModeFreeResources(res);
|
||||
return EINA_TRUE;
|
||||
|
||||
err:
|
||||
eina_thread_queue_free(thq);
|
||||
thq = NULL;
|
||||
_ecore_drm2_crtcs_destroy(dev);
|
||||
sym_drmModeFreeCrtc(c);
|
||||
sym_drmModeFreeResources(res);
|
||||
return EINA_FALSE;
|
||||
}
|
||||
|
||||
void
|
||||
_ecore_drm2_crtcs_destroy(Ecore_Drm2_Device *dev)
|
||||
{
|
||||
Ecore_Drm2_Crtc *crtc;
|
||||
|
||||
EINA_LIST_FREE(dev->crtcs, crtc)
|
||||
{
|
||||
if (crtc->thread) ecore_thread_cancel(crtc->thread);
|
||||
if (crtc->drmCrtc) sym_drmModeFreeCrtc(crtc->drmCrtc);
|
||||
free(crtc->state.pending);
|
||||
free(crtc->state.current);
|
||||
free(crtc);
|
||||
}
|
||||
|
||||
if (thq)
|
||||
{
|
||||
eina_thread_queue_free(thq);
|
||||
thq = NULL;
|
||||
}
|
||||
}
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,952 @@
|
|||
#include "ecore_drm2_private.h"
|
||||
|
||||
#define EDID_DESCRIPTOR_ALPHANUMERIC_DATA_STRING 0xfe
|
||||
#define EDID_DESCRIPTOR_DISPLAY_PRODUCT_NAME 0xfc
|
||||
#define EDID_DESCRIPTOR_DISPLAY_PRODUCT_SERIAL_NUMBER 0xff
|
||||
#define EDID_OFFSET_DATA_BLOCKS 0x36
|
||||
#define EDID_OFFSET_LAST_BLOCK 0x6c
|
||||
#define EDID_OFFSET_PNPID 0x08
|
||||
#define EDID_OFFSET_SERIAL 0x0c
|
||||
|
||||
static Eina_Thread_Queue *thq = NULL;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
Eina_Thread_Queue_Msg head;
|
||||
Ecore_Drm2_Thread_Op_Code code;
|
||||
} Thread_Msg;
|
||||
|
||||
static const char *conn_types[] =
|
||||
{
|
||||
"None", "VGA", "DVI-I", "DVI-D", "DVI-A",
|
||||
"Composite", "S-Video", "LVDS", "Component", "DIN",
|
||||
"DisplayPort", "HDMI-A", "HDMI-B", "TV", "eDP", "Virtual", "DSI",
|
||||
};
|
||||
|
||||
static void
|
||||
_ecore_drm2_display_state_thread_send(Ecore_Drm2_Thread_Op_Code code)
|
||||
{
|
||||
Thread_Msg *msg;
|
||||
void *ref;
|
||||
|
||||
msg = eina_thread_queue_send(thq, sizeof(Thread_Msg), &ref);
|
||||
msg->code = code;
|
||||
eina_thread_queue_send_done(thq, ref);
|
||||
}
|
||||
|
||||
static char *
|
||||
_ecore_drm2_display_name_get(Ecore_Drm2_Connector *conn)
|
||||
{
|
||||
char name[DRM_CONNECTOR_NAME_LEN];
|
||||
const char *type = NULL;
|
||||
|
||||
if (conn->type < EINA_C_ARRAY_LENGTH(conn_types))
|
||||
type = conn_types[conn->type];
|
||||
else
|
||||
type = "UNKNOWN";
|
||||
|
||||
snprintf(name, sizeof(name), "%s-%d", type, conn->drmConn->connector_type_id);
|
||||
return strdup(name);
|
||||
}
|
||||
|
||||
static void
|
||||
_ecore_drm2_display_edid_parse_string(const uint8_t *data, char text[])
|
||||
{
|
||||
int i = 0, rep = 0;
|
||||
|
||||
strncpy(text, (const char *)data, 12);
|
||||
|
||||
for (; text[i] != '\0'; i++)
|
||||
{
|
||||
if ((text[i] == '\n') || (text[i] == '\r'))
|
||||
{
|
||||
text[i] = '\0';
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
for (i = 0; text[i] != '\0'; i++)
|
||||
{
|
||||
if (!isprint(text[i]))
|
||||
{
|
||||
text[i] = '-';
|
||||
rep++;
|
||||
}
|
||||
}
|
||||
|
||||
if (rep > 4) text[0] = '\0';
|
||||
}
|
||||
|
||||
static int
|
||||
_ecore_drm2_display_edid_parse(Ecore_Drm2_Display *disp, const uint8_t *data, size_t len)
|
||||
{
|
||||
int i = 0;
|
||||
uint32_t serial;
|
||||
|
||||
if (len < 128) return -1;
|
||||
if ((data[0] != 0x00) || (data[1] != 0xff)) return -1;
|
||||
|
||||
disp->edid.pnp[0] = 'A' + ((data[EDID_OFFSET_PNPID + 0] & 0x7c) / 4) - 1;
|
||||
disp->edid.pnp[1] =
|
||||
'A' + ((data[EDID_OFFSET_PNPID + 0] & 0x3) * 8) +
|
||||
((data[EDID_OFFSET_PNPID + 1] & 0xe0) / 32) - 1;
|
||||
disp->edid.pnp[2] = 'A' + (data[EDID_OFFSET_PNPID + 1] & 0x1f) - 1;
|
||||
disp->edid.pnp[3] = '\0';
|
||||
|
||||
serial = (uint32_t) data[EDID_OFFSET_SERIAL + 0];
|
||||
serial += (uint32_t) data[EDID_OFFSET_SERIAL + 1] * 0x100;
|
||||
serial += (uint32_t) data[EDID_OFFSET_SERIAL + 2] * 0x10000;
|
||||
serial += (uint32_t) data[EDID_OFFSET_SERIAL + 3] * 0x1000000;
|
||||
if (serial > 0)
|
||||
sprintf(disp->edid.serial, "%lu", (unsigned long)serial);
|
||||
|
||||
for (i = EDID_OFFSET_DATA_BLOCKS; i <= EDID_OFFSET_LAST_BLOCK; i += 18)
|
||||
{
|
||||
if (data[i] != 0) continue;
|
||||
if (data[i + 2] != 0) continue;
|
||||
|
||||
if (data[i + 3] == EDID_DESCRIPTOR_DISPLAY_PRODUCT_NAME)
|
||||
_ecore_drm2_display_edid_parse_string(&data[i + 5], disp->edid.monitor);
|
||||
else if (data[i + 3] == EDID_DESCRIPTOR_DISPLAY_PRODUCT_SERIAL_NUMBER)
|
||||
_ecore_drm2_display_edid_parse_string(&data[i + 5], disp->edid.serial);
|
||||
else if (data[i + 3] == EDID_DESCRIPTOR_ALPHANUMERIC_DATA_STRING)
|
||||
_ecore_drm2_display_edid_parse_string(&data[i + 5], disp->edid.eisa);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void
|
||||
_ecore_drm2_display_edid_get(Ecore_Drm2_Display *disp)
|
||||
{
|
||||
Ecore_Drm2_Connector_State *cstate;
|
||||
int ret = 0;
|
||||
|
||||
cstate = disp->conn->state.current;
|
||||
|
||||
ret = _ecore_drm2_display_edid_parse(disp, cstate->edid.data, cstate->edid.len);
|
||||
if (!ret)
|
||||
{
|
||||
if (disp->edid.pnp[0] != '\0')
|
||||
eina_stringshare_replace(&disp->make, disp->edid.pnp);
|
||||
if (disp->edid.monitor[0] != '\0')
|
||||
eina_stringshare_replace(&disp->model, disp->edid.monitor);
|
||||
if (disp->edid.serial[0] != '\0')
|
||||
eina_stringshare_replace(&disp->serial, disp->edid.serial);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
_ecore_drm2_display_state_debug(Ecore_Drm2_Display *disp)
|
||||
{
|
||||
Eina_List *l = NULL;
|
||||
Ecore_Drm2_Display_Mode *mode;
|
||||
|
||||
DBG("Display Atomic State Fill Complete");
|
||||
|
||||
DBG("\tName: %s", disp->name);
|
||||
DBG("\tMake: %s", disp->make);
|
||||
DBG("\tModel: %s", disp->model);
|
||||
DBG("\tSerial: %s", disp->serial);
|
||||
|
||||
DBG("\tCrtc: %d", disp->crtc->id);
|
||||
DBG("\tCrtc Pos: %d %d", disp->crtc->drmCrtc->x, disp->crtc->drmCrtc->y);
|
||||
DBG("\tConnector: %d", disp->conn->id);
|
||||
|
||||
if (disp->backlight.path)
|
||||
{
|
||||
DBG("\tBacklight");
|
||||
switch (disp->backlight.type)
|
||||
{
|
||||
case ECORE_DRM2_BACKLIGHT_RAW:
|
||||
DBG("\t\tType: Raw");
|
||||
break;
|
||||
case ECORE_DRM2_BACKLIGHT_PLATFORM:
|
||||
DBG("\t\tType: Platform");
|
||||
break;
|
||||
case ECORE_DRM2_BACKLIGHT_FIRMWARE:
|
||||
DBG("\t\tType: Firmware");
|
||||
break;
|
||||
}
|
||||
DBG("\t\tPath: %s", disp->backlight.path);
|
||||
}
|
||||
|
||||
EINA_LIST_FOREACH(disp->modes, l, mode)
|
||||
{
|
||||
DBG("\tAdded Mode: %dx%d@%.1f%s%s%s, %.1f MHz",
|
||||
mode->width, mode->height, mode->refresh / 1000.0,
|
||||
(mode->flags & DRM_MODE_TYPE_PREFERRED) ? ", preferred" : "",
|
||||
(mode->flags & DRM_MODE_TYPE_DEFAULT) ? ", current" : "",
|
||||
(disp->conn->drmConn->count_modes == 0) ? ", built-in" : "",
|
||||
mode->info.clock / 1000.0);
|
||||
}
|
||||
|
||||
/* DBG("\tCloned: %d", disp->cloned); */
|
||||
DBG("\tPrimary: %d", disp->state.current->primary);
|
||||
DBG("\tEnabled: %d", disp->state.current->enabled);
|
||||
DBG("\tConnected: %d", disp->connected);
|
||||
}
|
||||
|
||||
static double
|
||||
_ecore_drm2_display_backlight_value_get(Ecore_Drm2_Display *disp, const char *attr)
|
||||
{
|
||||
const char *b = NULL;
|
||||
double ret = 0.0;
|
||||
|
||||
if ((!disp) || (!disp->backlight.path)) return 0.0;
|
||||
|
||||
b = eeze_udev_syspath_get_sysattr(disp->backlight.path, attr);
|
||||
if (!b) return 0.0;
|
||||
|
||||
ret = strtod(b, NULL);
|
||||
if (ret < 0) ret = 0.0;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void
|
||||
_ecore_drm2_display_backlight_get(Ecore_Drm2_Display *disp)
|
||||
{
|
||||
Eina_List *devs, *l;
|
||||
const char *dev, *t;
|
||||
Ecore_Drm2_Backlight_Type type = 0;
|
||||
Eina_Bool found = EINA_FALSE;
|
||||
|
||||
devs = eeze_udev_find_by_filter("backlight", NULL, NULL);
|
||||
|
||||
EINA_LIST_FOREACH(devs, l, dev)
|
||||
{
|
||||
t = eeze_udev_syspath_get_sysattr(dev, "type");
|
||||
if (!t) continue;
|
||||
|
||||
if (!strcmp(t, "raw"))
|
||||
type = ECORE_DRM2_BACKLIGHT_RAW;
|
||||
else if (!strcmp(t, "platform"))
|
||||
type = ECORE_DRM2_BACKLIGHT_PLATFORM;
|
||||
else if (!strcmp(t, "firmware"))
|
||||
type = ECORE_DRM2_BACKLIGHT_FIRMWARE;
|
||||
|
||||
if ((disp->conn->type == DRM_MODE_CONNECTOR_LVDS) ||
|
||||
(disp->conn->type == DRM_MODE_CONNECTOR_eDP) ||
|
||||
(type == ECORE_DRM2_BACKLIGHT_RAW))
|
||||
found = EINA_TRUE;
|
||||
|
||||
eina_stringshare_del(t);
|
||||
if (found) break;
|
||||
}
|
||||
|
||||
if (found)
|
||||
{
|
||||
disp->backlight.type = type;
|
||||
disp->backlight.path = eina_stringshare_add(dev);
|
||||
disp->backlight.max =
|
||||
_ecore_drm2_display_backlight_value_get(disp, "max_brightness");
|
||||
disp->state.current->backlight =
|
||||
_ecore_drm2_display_backlight_value_get(disp, "brightness");
|
||||
}
|
||||
|
||||
EINA_LIST_FREE(devs, dev)
|
||||
eina_stringshare_del(dev);
|
||||
}
|
||||
|
||||
static Ecore_Drm2_Display_Mode *
|
||||
_ecore_drm2_display_mode_create(const drmModeModeInfo *info)
|
||||
{
|
||||
Ecore_Drm2_Display_Mode *mode;
|
||||
uint64_t refresh;
|
||||
|
||||
EINA_SAFETY_ON_NULL_RETURN_VAL(info, NULL);
|
||||
EINA_SAFETY_ON_FALSE_RETURN_VAL((info->htotal > 0), NULL);
|
||||
EINA_SAFETY_ON_FALSE_RETURN_VAL((info->vtotal > 0), NULL);
|
||||
|
||||
mode = calloc(1, sizeof(Ecore_Drm2_Display_Mode));
|
||||
if (!mode) return NULL;
|
||||
|
||||
mode->flags = 0;
|
||||
mode->width = info->hdisplay;
|
||||
mode->height = info->vdisplay;
|
||||
|
||||
refresh = (info->clock * 1000000LL / info->htotal +
|
||||
info->vtotal / 2) / info->vtotal;
|
||||
|
||||
if (info->flags & DRM_MODE_FLAG_INTERLACE)
|
||||
refresh *= 2;
|
||||
if (info->flags & DRM_MODE_FLAG_DBLSCAN)
|
||||
refresh /= 2;
|
||||
if (info->vscan > 1)
|
||||
refresh /= info->vscan;
|
||||
|
||||
mode->refresh = refresh;
|
||||
mode->info = *info;
|
||||
|
||||
if (info->type & DRM_MODE_TYPE_PREFERRED)
|
||||
mode->flags |= DRM_MODE_TYPE_PREFERRED;
|
||||
|
||||
return mode;
|
||||
}
|
||||
|
||||
static void
|
||||
_ecore_drm2_display_modes_get(Ecore_Drm2_Display *disp)
|
||||
{
|
||||
int i = 0;
|
||||
drmModeModeInfo crtc_mode;
|
||||
Ecore_Drm2_Display_Mode *dmode;
|
||||
Ecore_Drm2_Display_Mode *current = NULL, *pref = NULL, *best = NULL;
|
||||
Eina_List *l = NULL;
|
||||
|
||||
memset(&crtc_mode, 0, sizeof(crtc_mode));
|
||||
|
||||
if (disp->crtc->drmCrtc->mode_valid)
|
||||
crtc_mode = disp->crtc->drmCrtc->mode;
|
||||
|
||||
/* loop through connector modes and try to create mode */
|
||||
for (; i < disp->conn->drmConn->count_modes; i++)
|
||||
{
|
||||
dmode =
|
||||
_ecore_drm2_display_mode_create(&disp->conn->drmConn->modes[i]);
|
||||
if (!dmode) continue;
|
||||
|
||||
/* append mode to display mode list */
|
||||
disp->modes = eina_list_append(disp->modes, dmode);
|
||||
}
|
||||
|
||||
/* try to select current mode */
|
||||
EINA_LIST_REVERSE_FOREACH(disp->modes, l, dmode)
|
||||
{
|
||||
if (!memcmp(&crtc_mode, &dmode->info, sizeof(crtc_mode)))
|
||||
current = dmode;
|
||||
if (dmode->flags & DRM_MODE_TYPE_PREFERRED)
|
||||
pref = dmode;
|
||||
best = dmode;
|
||||
}
|
||||
|
||||
if ((!current) && (crtc_mode.clock != 0))
|
||||
{
|
||||
current = _ecore_drm2_display_mode_create(&crtc_mode);
|
||||
if (!current) goto err;
|
||||
disp->modes = eina_list_append(disp->modes, current);
|
||||
}
|
||||
|
||||
if (current) disp->state.current->mode = current;
|
||||
else if (pref) disp->state.current->mode = pref;
|
||||
else if (best) disp->state.current->mode = best;
|
||||
|
||||
if (!disp->state.current->mode) goto err;
|
||||
|
||||
disp->state.current->mode->flags |= DRM_MODE_TYPE_DEFAULT;
|
||||
|
||||
return;
|
||||
|
||||
err:
|
||||
EINA_LIST_FREE(disp->modes, dmode)
|
||||
free(dmode);
|
||||
}
|
||||
|
||||
static void
|
||||
_ecore_drm2_display_rotation_get(Ecore_Drm2_Display *disp)
|
||||
{
|
||||
Ecore_Drm2_Plane *plane;
|
||||
|
||||
/* try to find primary plane for this display */
|
||||
plane = _ecore_drm2_planes_primary_find(disp->dev, disp->crtc->id);
|
||||
if (plane)
|
||||
{
|
||||
if (plane->state.current)
|
||||
disp->state.current->rotation = plane->state.current->rotation.value;
|
||||
else
|
||||
{
|
||||
drmModeObjectPropertiesPtr oprops;
|
||||
|
||||
/* NB: Sadly we cannot rely on plane->state.current being already
|
||||
* filled by the time we reach this (due to threading),
|
||||
* so we will query the plane properties we want directly */
|
||||
|
||||
/* query plane for rotations */
|
||||
oprops =
|
||||
sym_drmModeObjectGetProperties(plane->fd,
|
||||
plane->drmPlane->plane_id,
|
||||
DRM_MODE_OBJECT_PLANE);
|
||||
if (oprops)
|
||||
{
|
||||
unsigned int i = 0;
|
||||
|
||||
for (; i < oprops->count_props; i++)
|
||||
{
|
||||
drmModePropertyPtr prop;
|
||||
|
||||
prop = sym_drmModeGetProperty(plane->fd, oprops->props[i]);
|
||||
if (!prop) continue;
|
||||
|
||||
if (!strcmp(prop->name, "rotation"))
|
||||
disp->state.current->rotation = oprops->prop_values[i];
|
||||
|
||||
sym_drmModeFreeProperty(prop);
|
||||
}
|
||||
sym_drmModeFreeObjectProperties(oprops);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
_ecore_drm2_display_state_fill(Ecore_Drm2_Display *disp)
|
||||
{
|
||||
char *name = NULL;
|
||||
|
||||
/* try to allocate space for current Display state */
|
||||
disp->state.current = calloc(1, sizeof(Ecore_Drm2_Display_State));
|
||||
if (!disp->state.current)
|
||||
{
|
||||
ERR("Could not allocate space for Display state");
|
||||
return;
|
||||
}
|
||||
|
||||
/* get display name */
|
||||
name = _ecore_drm2_display_name_get(disp->conn);
|
||||
disp->name = eina_stringshare_add(name);
|
||||
free(name);
|
||||
|
||||
disp->make = eina_stringshare_add("unknown");
|
||||
disp->model = eina_stringshare_add("unknown");
|
||||
disp->serial = eina_stringshare_add("unknown");
|
||||
|
||||
/* get edid and parse */
|
||||
_ecore_drm2_display_edid_get(disp);
|
||||
|
||||
/* get physical dimensions */
|
||||
disp->pw = disp->conn->drmConn->mmWidth;
|
||||
disp->ph = disp->conn->drmConn->mmHeight;
|
||||
|
||||
/* get subpixel */
|
||||
switch (disp->conn->drmConn->subpixel)
|
||||
{
|
||||
case DRM_MODE_SUBPIXEL_NONE:
|
||||
disp->subpixel = 1;
|
||||
break;
|
||||
case DRM_MODE_SUBPIXEL_HORIZONTAL_RGB:
|
||||
disp->subpixel = 2;
|
||||
break;
|
||||
case DRM_MODE_SUBPIXEL_HORIZONTAL_BGR:
|
||||
disp->subpixel = 3;
|
||||
break;
|
||||
case DRM_MODE_SUBPIXEL_VERTICAL_RGB:
|
||||
disp->subpixel = 4;
|
||||
break;
|
||||
case DRM_MODE_SUBPIXEL_VERTICAL_BGR:
|
||||
disp->subpixel = 5;
|
||||
break;
|
||||
case DRM_MODE_SUBPIXEL_UNKNOWN:
|
||||
default:
|
||||
disp->subpixel = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
/* get current rotation value */
|
||||
_ecore_drm2_display_rotation_get(disp);
|
||||
|
||||
/* get backlight values */
|
||||
_ecore_drm2_display_backlight_get(disp);
|
||||
|
||||
/* get available display modes */
|
||||
_ecore_drm2_display_modes_get(disp);
|
||||
|
||||
/* get gamma from crtc */
|
||||
disp->state.current->gamma = disp->crtc->drmCrtc->gamma_size;
|
||||
|
||||
/* get connected state */
|
||||
disp->connected = (disp->conn->drmConn->connection == DRM_MODE_CONNECTED);
|
||||
|
||||
/* duplicate current state into pending so we can handle changes */
|
||||
disp->state.pending = calloc(1, sizeof(Ecore_Drm2_Display_State));
|
||||
if (disp->state.pending)
|
||||
memcpy(disp->state.pending, disp->state.current, sizeof(Ecore_Drm2_Display_State));
|
||||
|
||||
/* send message to thread for debug printing display state */
|
||||
_ecore_drm2_display_state_thread_send(ECORE_DRM2_THREAD_CODE_DEBUG);
|
||||
}
|
||||
|
||||
static void
|
||||
_ecore_drm2_display_state_thread(void *data, Ecore_Thread *thread EINA_UNUSED)
|
||||
{
|
||||
Ecore_Drm2_Display *disp;
|
||||
Thread_Msg *msg;
|
||||
void *ref;
|
||||
|
||||
disp = data;
|
||||
|
||||
eina_thread_name_set(eina_thread_self(), "Ecore-drm2-display");
|
||||
|
||||
while (!ecore_thread_check(thread))
|
||||
{
|
||||
msg = eina_thread_queue_wait(thq, &ref);
|
||||
if (msg)
|
||||
{
|
||||
switch (msg->code)
|
||||
{
|
||||
case ECORE_DRM2_THREAD_CODE_FILL:
|
||||
_ecore_drm2_display_state_fill(disp);
|
||||
break;
|
||||
case ECORE_DRM2_THREAD_CODE_DEBUG:
|
||||
_ecore_drm2_display_state_debug(disp);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
eina_thread_queue_wait_done(thq, ref);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
_ecore_drm2_display_state_thread_notify(void *data EINA_UNUSED, Ecore_Thread *thread EINA_UNUSED, void *msg)
|
||||
{
|
||||
free(msg);
|
||||
}
|
||||
|
||||
Eina_Bool
|
||||
_ecore_drm2_displays_create(Ecore_Drm2_Device *dev)
|
||||
{
|
||||
Ecore_Drm2_Display *disp;
|
||||
Ecore_Drm2_Connector *c;
|
||||
Ecore_Drm2_Crtc *crtc;
|
||||
Eina_List *l = NULL, *ll = NULL;
|
||||
|
||||
thq = eina_thread_queue_new();
|
||||
|
||||
/* go through list of connectors and create displays */
|
||||
EINA_LIST_FOREACH(dev->conns, l, c)
|
||||
{
|
||||
drmModeEncoder *encoder;
|
||||
drmModeCrtc *dcrtc;
|
||||
|
||||
/* try to get the encoder from drm */
|
||||
encoder = sym_drmModeGetEncoder(dev->fd, c->drmConn->encoder_id);
|
||||
if (!encoder) continue;
|
||||
|
||||
/* try to get the crtc from drm */
|
||||
dcrtc = sym_drmModeGetCrtc(dev->fd, encoder->crtc_id);
|
||||
if (!dcrtc) goto cont;
|
||||
|
||||
/* try to allocate space for new display */
|
||||
disp = calloc(1, sizeof(Ecore_Drm2_Display));
|
||||
if (!disp)
|
||||
{
|
||||
WRN("Could not allocate space for Display");
|
||||
sym_drmModeFreeCrtc(dcrtc);
|
||||
goto cont;
|
||||
}
|
||||
|
||||
disp->dev = dev;
|
||||
|
||||
/* try to find crtc matching dcrtc->crtc_id and assign to display */
|
||||
EINA_LIST_FOREACH(dev->crtcs, ll, crtc)
|
||||
{
|
||||
if (crtc->id == dcrtc->crtc_id)
|
||||
{
|
||||
disp->crtc = crtc;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
sym_drmModeFreeCrtc(dcrtc);
|
||||
|
||||
/* disp->fd = dev->fd; */
|
||||
disp->conn = c;
|
||||
|
||||
/* append this display to the list */
|
||||
dev->displays = eina_list_append(dev->displays, disp);
|
||||
|
||||
disp->thread =
|
||||
ecore_thread_feedback_run(_ecore_drm2_display_state_thread,
|
||||
_ecore_drm2_display_state_thread_notify,
|
||||
NULL, NULL, disp, EINA_TRUE);
|
||||
|
||||
cont:
|
||||
sym_drmModeFreeEncoder(encoder);
|
||||
}
|
||||
|
||||
return EINA_TRUE;
|
||||
}
|
||||
|
||||
void
|
||||
_ecore_drm2_displays_destroy(Ecore_Drm2_Device *dev)
|
||||
{
|
||||
Ecore_Drm2_Display *disp;
|
||||
|
||||
EINA_LIST_FREE(dev->displays, disp)
|
||||
{
|
||||
if (disp->thread) ecore_thread_cancel(disp->thread);
|
||||
eina_stringshare_del(disp->backlight.path);
|
||||
eina_stringshare_del(disp->relative.to);
|
||||
eina_stringshare_del(disp->serial);
|
||||
eina_stringshare_del(disp->model);
|
||||
eina_stringshare_del(disp->make);
|
||||
eina_stringshare_del(disp->name);
|
||||
free(disp->state.pending);
|
||||
free(disp->state.current);
|
||||
free(disp);
|
||||
}
|
||||
|
||||
if (thq)
|
||||
{
|
||||
eina_thread_queue_free(thq);
|
||||
thq = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
EAPI char *
|
||||
ecore_drm2_display_name_get(Ecore_Drm2_Display *disp)
|
||||
{
|
||||
EINA_SAFETY_ON_NULL_RETURN_VAL(disp, NULL);
|
||||
EINA_SAFETY_ON_NULL_RETURN_VAL(disp->name, NULL);
|
||||
return strdup(disp->name);
|
||||
}
|
||||
|
||||
EAPI char *
|
||||
ecore_drm2_display_model_get(Ecore_Drm2_Display *disp)
|
||||
{
|
||||
EINA_SAFETY_ON_NULL_RETURN_VAL(disp, NULL);
|
||||
EINA_SAFETY_ON_NULL_RETURN_VAL(disp->model, NULL);
|
||||
return strdup(disp->model);
|
||||
}
|
||||
|
||||
EAPI void
|
||||
ecore_drm2_display_mode_set(Ecore_Drm2_Display *disp, Ecore_Drm2_Display_Mode *mode, int x, int y)
|
||||
{
|
||||
Ecore_Drm2_Display_State *cstate, *pstate;
|
||||
|
||||
EINA_SAFETY_ON_NULL_RETURN(disp);
|
||||
EINA_SAFETY_ON_NULL_RETURN(mode);
|
||||
EINA_SAFETY_ON_NULL_RETURN(disp->crtc);
|
||||
|
||||
cstate = disp->state.current;
|
||||
pstate = disp->state.pending;
|
||||
|
||||
if ((cstate->x != x) || (cstate->y != y))
|
||||
{
|
||||
pstate->x = x;
|
||||
pstate->y = y;
|
||||
pstate->changes |= ECORE_DRM2_DISPLAY_STATE_POSITION;
|
||||
}
|
||||
|
||||
if (cstate->mode != mode)
|
||||
{
|
||||
pstate->mode = mode;
|
||||
pstate->changes |= ECORE_DRM2_DISPLAY_STATE_MODE;
|
||||
}
|
||||
}
|
||||
|
||||
EAPI Eina_Bool
|
||||
ecore_drm2_display_backlight_get(Ecore_Drm2_Display *disp)
|
||||
{
|
||||
EINA_SAFETY_ON_NULL_RETURN_VAL(disp, EINA_FALSE);
|
||||
return (disp->backlight.path != NULL);
|
||||
}
|
||||
|
||||
EAPI Eina_Bool
|
||||
ecore_drm2_display_connected_get(Ecore_Drm2_Display *disp)
|
||||
{
|
||||
EINA_SAFETY_ON_NULL_RETURN_VAL(disp, EINA_FALSE);
|
||||
return disp->connected;
|
||||
}
|
||||
|
||||
EAPI unsigned int
|
||||
ecore_drm2_display_connector_type_get(Ecore_Drm2_Display *disp)
|
||||
{
|
||||
EINA_SAFETY_ON_NULL_RETURN_VAL(disp, 0);
|
||||
EINA_SAFETY_ON_NULL_RETURN_VAL(disp->conn, 0);
|
||||
return disp->conn->type;
|
||||
}
|
||||
|
||||
EAPI unsigned int
|
||||
ecore_drm2_display_subpixel_get(Ecore_Drm2_Display *disp)
|
||||
{
|
||||
EINA_SAFETY_ON_NULL_RETURN_VAL(disp, 0);
|
||||
return disp->subpixel;
|
||||
}
|
||||
|
||||
EAPI void
|
||||
ecore_drm2_display_physical_size_get(Ecore_Drm2_Display *disp, int *w, int *h)
|
||||
{
|
||||
if (w) *w = 0;
|
||||
if (h) *h = 0;
|
||||
|
||||
EINA_SAFETY_ON_NULL_RETURN(disp);
|
||||
|
||||
if (w) *w = disp->pw;
|
||||
if (h) *h = disp->ph;
|
||||
}
|
||||
|
||||
EAPI int
|
||||
ecore_drm2_display_dpms_get(Ecore_Drm2_Display *disp)
|
||||
{
|
||||
EINA_SAFETY_ON_NULL_RETURN_VAL(disp, -1);
|
||||
EINA_SAFETY_ON_NULL_RETURN_VAL(disp->conn, -1);
|
||||
return disp->conn->state.current->dpms.value;
|
||||
}
|
||||
|
||||
EAPI void
|
||||
ecore_drm2_display_dpms_set(Ecore_Drm2_Display *disp, uint64_t level)
|
||||
{
|
||||
Ecore_Drm2_Connector_State *cstate, *pstate;
|
||||
|
||||
EINA_SAFETY_ON_NULL_RETURN(disp);
|
||||
EINA_SAFETY_ON_NULL_RETURN(disp->conn);
|
||||
|
||||
cstate = disp->conn->state.current;
|
||||
if (cstate->dpms.value == level) return;
|
||||
|
||||
pstate = disp->conn->state.pending;
|
||||
pstate->dpms.value = level;
|
||||
pstate->changes |= ECORE_DRM2_CONNECTOR_STATE_DPMS;
|
||||
}
|
||||
|
||||
EAPI Eina_Bool
|
||||
ecore_drm2_display_enabled_get(Ecore_Drm2_Display *disp)
|
||||
{
|
||||
EINA_SAFETY_ON_NULL_RETURN_VAL(disp, EINA_FALSE);
|
||||
return disp->state.current->enabled;
|
||||
}
|
||||
|
||||
EAPI void
|
||||
ecore_drm2_display_enabled_set(Ecore_Drm2_Display *disp, Eina_Bool enabled)
|
||||
{
|
||||
Ecore_Drm2_Display_State *cstate, *pstate;
|
||||
|
||||
EINA_SAFETY_ON_NULL_RETURN(disp);
|
||||
|
||||
cstate = disp->state.current;
|
||||
pstate = disp->state.pending;
|
||||
|
||||
if (cstate->enabled == enabled) return;
|
||||
|
||||
/* TODO, FIXME */
|
||||
|
||||
pstate->enabled = enabled;
|
||||
pstate->changes |= ECORE_DRM2_DISPLAY_STATE_ENABLED;
|
||||
}
|
||||
|
||||
EAPI char *
|
||||
ecore_drm2_display_edid_get(Ecore_Drm2_Display *disp)
|
||||
{
|
||||
char *edid_str = NULL;
|
||||
unsigned char *blob;
|
||||
unsigned char fblob[128];
|
||||
|
||||
EINA_SAFETY_ON_NULL_RETURN_VAL(disp, NULL);
|
||||
EINA_SAFETY_ON_NULL_RETURN_VAL(disp->conn, NULL);
|
||||
EINA_SAFETY_ON_NULL_RETURN_VAL(disp->conn->state.current, NULL);
|
||||
|
||||
blob = disp->conn->state.current->edid.data;
|
||||
if (!blob)
|
||||
{
|
||||
memset(fblob, 0, sizeof(fblob));
|
||||
blob = fblob;
|
||||
}
|
||||
|
||||
edid_str = malloc((128 * 2) + 1);
|
||||
if (edid_str)
|
||||
{
|
||||
unsigned int k, kk;
|
||||
const char *hexch = "0123456789abcdef";
|
||||
|
||||
for (kk = 0, k = 0; k < 128; k++)
|
||||
{
|
||||
edid_str[kk] = hexch[(blob[k] >> 4) & 0xf];
|
||||
edid_str[kk + 1] = hexch[blob[k] & 0xf];
|
||||
kk += 2;
|
||||
}
|
||||
edid_str[kk] = 0;
|
||||
}
|
||||
|
||||
return edid_str;
|
||||
}
|
||||
|
||||
EAPI const Eina_List *
|
||||
ecore_drm2_display_modes_get(Ecore_Drm2_Display *disp)
|
||||
{
|
||||
EINA_SAFETY_ON_NULL_RETURN_VAL(disp, NULL);
|
||||
return disp->modes;
|
||||
}
|
||||
|
||||
EAPI void
|
||||
ecore_drm2_display_mode_info_get(Ecore_Drm2_Display_Mode *mode, int *w, int *h, unsigned int *refresh, unsigned int *flags)
|
||||
{
|
||||
if (w) *w = 0;
|
||||
if (h) *h = 0;
|
||||
if (refresh) *refresh = 0;
|
||||
if (flags) *flags = 0;
|
||||
|
||||
EINA_SAFETY_ON_NULL_RETURN(mode);
|
||||
|
||||
if (w) *w = mode->width;
|
||||
if (h) *h = mode->height;
|
||||
if (refresh) *refresh = mode->refresh;
|
||||
if (flags) *flags = mode->flags;
|
||||
}
|
||||
|
||||
EAPI Eina_Bool
|
||||
ecore_drm2_display_primary_get(Ecore_Drm2_Display *disp)
|
||||
{
|
||||
EINA_SAFETY_ON_NULL_RETURN_VAL(disp, EINA_FALSE);
|
||||
return disp->state.current->primary;
|
||||
}
|
||||
|
||||
EAPI void
|
||||
ecore_drm2_display_primary_set(Ecore_Drm2_Display *disp, Eina_Bool primary)
|
||||
{
|
||||
Ecore_Drm2_Display_State *cstate, *pstate;
|
||||
|
||||
EINA_SAFETY_ON_NULL_RETURN(disp);
|
||||
|
||||
cstate = disp->state.current;
|
||||
pstate = disp->state.pending;
|
||||
|
||||
if (cstate->primary == primary) return;
|
||||
|
||||
/* TODO, FIXME */
|
||||
|
||||
pstate->primary = primary;
|
||||
pstate->changes |= ECORE_DRM2_DISPLAY_STATE_PRIMARY;
|
||||
}
|
||||
|
||||
EAPI const Eina_List *
|
||||
ecore_drm2_displays_get(Ecore_Drm2_Device *dev)
|
||||
{
|
||||
EINA_SAFETY_ON_NULL_RETURN_VAL(dev, EINA_FALSE);
|
||||
return dev->displays;
|
||||
}
|
||||
|
||||
EAPI void
|
||||
ecore_drm2_display_info_get(Ecore_Drm2_Display *disp, int *x, int *y, int *w, int *h, unsigned int *refresh)
|
||||
{
|
||||
Ecore_Drm2_Display_State *cstate;
|
||||
|
||||
if (x) *x = 0;
|
||||
if (y) *y = 0;
|
||||
if (w) *w = 0;
|
||||
if (h) *h = 0;
|
||||
if (refresh) *refresh = 0;
|
||||
|
||||
EINA_SAFETY_ON_NULL_RETURN(disp);
|
||||
EINA_SAFETY_ON_TRUE_RETURN(!disp->state.current->mode);
|
||||
|
||||
if (x) *x = disp->x;
|
||||
if (y) *y = disp->y;
|
||||
|
||||
cstate = disp->state.current;
|
||||
|
||||
switch (cstate->rotation)
|
||||
{
|
||||
case ECORE_DRM2_ROTATION_90:
|
||||
case ECORE_DRM2_ROTATION_270:
|
||||
if (w) *w = cstate->mode->height;
|
||||
if (h) *h = cstate->mode->width;
|
||||
break;
|
||||
case ECORE_DRM2_ROTATION_NORMAL:
|
||||
case ECORE_DRM2_ROTATION_180:
|
||||
default:
|
||||
if (w) *w = cstate->mode->width;
|
||||
if (h) *h = cstate->mode->height;
|
||||
break;
|
||||
}
|
||||
|
||||
if (refresh) *refresh = cstate->mode->refresh;
|
||||
}
|
||||
|
||||
EAPI int
|
||||
ecore_drm2_display_rotation_get(Ecore_Drm2_Display *disp)
|
||||
{
|
||||
EINA_SAFETY_ON_NULL_RETURN_VAL(disp, -1);
|
||||
return disp->state.current->rotation;
|
||||
}
|
||||
|
||||
EAPI void
|
||||
ecore_drm2_display_rotation_set(Ecore_Drm2_Display *disp, uint64_t rotation)
|
||||
{
|
||||
Ecore_Drm2_Display_State *cstate, *pstate;
|
||||
|
||||
EINA_SAFETY_ON_NULL_RETURN(disp);
|
||||
|
||||
cstate = disp->state.current;
|
||||
pstate = disp->state.pending;
|
||||
|
||||
if (cstate->rotation == rotation) return;
|
||||
|
||||
/* TODO, FIXME */
|
||||
|
||||
pstate->rotation = rotation;
|
||||
pstate->changes |= ECORE_DRM2_DISPLAY_STATE_ROTATION;
|
||||
}
|
||||
|
||||
EAPI Ecore_Drm2_Crtc *
|
||||
ecore_drm2_display_crtc_get(Ecore_Drm2_Display *disp)
|
||||
{
|
||||
EINA_SAFETY_ON_NULL_RETURN_VAL(disp, NULL);
|
||||
return disp->crtc;
|
||||
}
|
||||
|
||||
EAPI Eina_Bool
|
||||
ecore_drm2_display_possible_crtc_get(Ecore_Drm2_Display *disp, Ecore_Drm2_Crtc *crtc)
|
||||
{
|
||||
drmModeConnector *conn;
|
||||
drmModeEncoder *enc;
|
||||
int i = 0;
|
||||
Eina_Bool ret = EINA_FALSE;
|
||||
|
||||
EINA_SAFETY_ON_NULL_RETURN_VAL(disp, EINA_FALSE);
|
||||
EINA_SAFETY_ON_NULL_RETURN_VAL(disp->conn, EINA_FALSE);
|
||||
EINA_SAFETY_ON_NULL_RETURN_VAL(disp->conn->drmConn, EINA_FALSE);
|
||||
EINA_SAFETY_ON_NULL_RETURN_VAL(crtc, EINA_FALSE);
|
||||
|
||||
conn = disp->conn->drmConn;
|
||||
for (; i < conn->count_encoders; i++)
|
||||
{
|
||||
enc = sym_drmModeGetEncoder(disp->conn->fd, conn->encoders[i]);
|
||||
if (!enc) continue;
|
||||
|
||||
if (enc->crtc_id != crtc->id) goto next;
|
||||
|
||||
if (enc->possible_crtcs & (1 << crtc->pipe))
|
||||
ret = EINA_TRUE;
|
||||
|
||||
next:
|
||||
sym_drmModeFreeEncoder(enc);
|
||||
if (ret) break;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
EAPI int
|
||||
ecore_drm2_display_supported_rotations_get(Ecore_Drm2_Display *disp)
|
||||
{
|
||||
Ecore_Drm2_Plane *plane;
|
||||
|
||||
EINA_SAFETY_ON_NULL_RETURN_VAL(disp, -1);
|
||||
|
||||
/* get the primary plane for this output */
|
||||
plane = _ecore_drm2_planes_primary_find(disp->dev, disp->crtc->id);
|
||||
if (!plane) return -1;
|
||||
|
||||
/* if plane state has not been filled yet, bail out */
|
||||
/* NB: We could modify this to get the plane rotations directly from drm */
|
||||
if (!plane->state.current) return -1;
|
||||
|
||||
/* return primary plane state supported_rotations */
|
||||
return plane->state.current->supported_rotations;
|
||||
}
|
||||
|
||||
EAPI void
|
||||
ecore_drm2_display_relative_mode_set(Ecore_Drm2_Display *disp, Ecore_Drm2_Relative_Mode mode)
|
||||
{
|
||||
EINA_SAFETY_ON_NULL_RETURN(disp);
|
||||
disp->relative.mode = mode;
|
||||
}
|
||||
|
||||
EAPI void
|
||||
ecore_drm2_display_relative_to_set(Ecore_Drm2_Display *disp, const char *relative)
|
||||
{
|
||||
EINA_SAFETY_ON_NULL_RETURN(disp);
|
||||
eina_stringshare_replace(&disp->relative.to, relative);
|
||||
}
|
|
@ -1,799 +0,0 @@
|
|||
#include "ecore_drm2_private.h"
|
||||
|
||||
#define FLIP_TIMEOUT 1.0
|
||||
|
||||
static Eina_Bool
|
||||
_fb2_create(Ecore_Drm2_Fb *fb)
|
||||
{
|
||||
uint32_t offsets[4] = { 0 };
|
||||
int r;
|
||||
|
||||
r = sym_drmModeAddFB2(fb->fd, fb->w, fb->h, fb->format, fb->handles,
|
||||
fb->strides, offsets, &fb->id, 0);
|
||||
|
||||
if (r)
|
||||
return EINA_FALSE;
|
||||
|
||||
return EINA_TRUE;
|
||||
}
|
||||
|
||||
EAPI Ecore_Drm2_Fb *
|
||||
ecore_drm2_fb_create(Ecore_Drm2_Device *dev, int width, int height, int depth, int bpp, unsigned int format)
|
||||
{
|
||||
Ecore_Drm2_Fb *fb;
|
||||
struct drm_mode_create_dumb carg;
|
||||
struct drm_mode_destroy_dumb darg;
|
||||
struct drm_mode_map_dumb marg;
|
||||
int ret;
|
||||
|
||||
EINA_SAFETY_ON_NULL_RETURN_VAL(dev, NULL);
|
||||
|
||||
fb = calloc(1, sizeof(Ecore_Drm2_Fb));
|
||||
if (!fb) return NULL;
|
||||
|
||||
fb->fd = dev->fd;
|
||||
fb->w = width;
|
||||
fb->h = height;
|
||||
fb->bpp = bpp;
|
||||
fb->depth = depth;
|
||||
fb->format = format;
|
||||
fb->ref = 1;
|
||||
|
||||
memset(&carg, 0, sizeof(struct drm_mode_create_dumb));
|
||||
carg.bpp = bpp;
|
||||
carg.width = width;
|
||||
carg.height = height;
|
||||
|
||||
ret = sym_drmIoctl(dev->fd, DRM_IOCTL_MODE_CREATE_DUMB, &carg);
|
||||
if (ret) goto err;
|
||||
|
||||
fb->handles[0] = carg.handle;
|
||||
fb->sizes[0] = carg.size;
|
||||
fb->strides[0] = carg.pitch;
|
||||
|
||||
if (!_fb2_create(fb))
|
||||
{
|
||||
ret =
|
||||
sym_drmModeAddFB(dev->fd, width, height, depth, bpp,
|
||||
fb->strides[0], fb->handles[0], &fb->id);
|
||||
if (ret)
|
||||
{
|
||||
ERR("Could not add framebuffer: %m");
|
||||
goto add_err;
|
||||
}
|
||||
}
|
||||
|
||||
memset(&marg, 0, sizeof(struct drm_mode_map_dumb));
|
||||
marg.handle = fb->handles[0];
|
||||
ret = sym_drmIoctl(dev->fd, DRM_IOCTL_MODE_MAP_DUMB, &marg);
|
||||
if (ret)
|
||||
{
|
||||
ERR("Could not map framebuffer: %m");
|
||||
goto map_err;
|
||||
}
|
||||
|
||||
fb->mmap = mmap(NULL, fb->sizes[0], PROT_WRITE, MAP_SHARED, dev->fd, marg.offset);
|
||||
if (fb->mmap == MAP_FAILED)
|
||||
{
|
||||
ERR("Could not mmap framebuffer memory: %m");
|
||||
goto map_err;
|
||||
}
|
||||
|
||||
return fb;
|
||||
|
||||
map_err:
|
||||
sym_drmModeRmFB(dev->fd, fb->id);
|
||||
add_err:
|
||||
memset(&darg, 0, sizeof(struct drm_mode_destroy_dumb));
|
||||
darg.handle = fb->handles[0];
|
||||
sym_drmIoctl(dev->fd, DRM_IOCTL_MODE_DESTROY_DUMB, &darg);
|
||||
err:
|
||||
free(fb);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
EAPI Ecore_Drm2_Fb *
|
||||
ecore_drm2_fb_gbm_create(Ecore_Drm2_Device *dev, int width, int height, int depth, int bpp, unsigned int format, unsigned int handle, unsigned int stride, void *bo)
|
||||
{
|
||||
Ecore_Drm2_Fb *fb;
|
||||
|
||||
EINA_SAFETY_ON_NULL_RETURN_VAL(dev, NULL);
|
||||
|
||||
fb = calloc(1, sizeof(Ecore_Drm2_Fb));
|
||||
if (!fb) return NULL;
|
||||
|
||||
fb->gbm = EINA_TRUE;
|
||||
fb->gbm_bo = bo;
|
||||
|
||||
fb->fd = dev->fd;
|
||||
fb->w = width;
|
||||
fb->h = height;
|
||||
fb->bpp = bpp;
|
||||
fb->depth = depth;
|
||||
fb->format = format;
|
||||
fb->strides[0] = stride;
|
||||
fb->sizes[0] = fb->strides[0] * fb->h;
|
||||
fb->handles[0] = handle;
|
||||
fb->ref = 1;
|
||||
|
||||
if (!_fb2_create(fb))
|
||||
{
|
||||
if (sym_drmModeAddFB(dev->fd, width, height, depth, bpp,
|
||||
fb->strides[0], fb->handles[0], &fb->id))
|
||||
{
|
||||
ERR("Could not add framebuffer: %m");
|
||||
goto err;
|
||||
}
|
||||
}
|
||||
return fb;
|
||||
|
||||
err:
|
||||
free(fb);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void
|
||||
_ecore_drm2_fb_destroy(Ecore_Drm2_Fb *fb)
|
||||
{
|
||||
EINA_SAFETY_ON_NULL_RETURN(fb);
|
||||
|
||||
if (!fb->dead) WRN("Destroying an fb that hasn't been discarded");
|
||||
|
||||
if (fb->scanout_count)
|
||||
WRN("Destroyed fb on scanout %d times.", fb->scanout_count);
|
||||
|
||||
if (fb->mmap) munmap(fb->mmap, fb->sizes[0]);
|
||||
|
||||
if (fb->id) sym_drmModeRmFB(fb->fd, fb->id);
|
||||
|
||||
if (!fb->gbm && !fb->dmabuf)
|
||||
{
|
||||
struct drm_mode_destroy_dumb darg;
|
||||
|
||||
memset(&darg, 0, sizeof(struct drm_mode_destroy_dumb));
|
||||
darg.handle = fb->handles[0];
|
||||
sym_drmIoctl(fb->fd, DRM_IOCTL_MODE_DESTROY_DUMB, &darg);
|
||||
}
|
||||
|
||||
free(fb);
|
||||
}
|
||||
|
||||
void
|
||||
_ecore_drm2_fb_ref(Ecore_Drm2_Fb *fb)
|
||||
{
|
||||
fb->ref++;
|
||||
}
|
||||
|
||||
void
|
||||
_ecore_drm2_fb_deref(Ecore_Drm2_Fb *fb)
|
||||
{
|
||||
fb->ref--;
|
||||
if (fb->ref) return;
|
||||
|
||||
if (fb->status_handler)
|
||||
fb->status_handler(fb, ECORE_DRM2_FB_STATUS_DELETED, fb->status_data);
|
||||
|
||||
_ecore_drm2_fb_destroy(fb);
|
||||
}
|
||||
|
||||
EAPI void
|
||||
ecore_drm2_fb_discard(Ecore_Drm2_Fb *fb)
|
||||
{
|
||||
EINA_SAFETY_ON_NULL_RETURN(fb);
|
||||
EINA_SAFETY_ON_TRUE_RETURN(fb->ref < 1);
|
||||
|
||||
fb->dead = EINA_TRUE;
|
||||
_ecore_drm2_fb_deref(fb);
|
||||
}
|
||||
|
||||
EAPI void *
|
||||
ecore_drm2_fb_data_get(Ecore_Drm2_Fb *fb)
|
||||
{
|
||||
EINA_SAFETY_ON_NULL_RETURN_VAL(fb, NULL);
|
||||
EINA_SAFETY_ON_TRUE_RETURN_VAL(fb->dead, NULL);
|
||||
return fb->mmap;
|
||||
}
|
||||
|
||||
EAPI unsigned int
|
||||
ecore_drm2_fb_size_get(Ecore_Drm2_Fb *fb)
|
||||
{
|
||||
EINA_SAFETY_ON_NULL_RETURN_VAL(fb, 0);
|
||||
EINA_SAFETY_ON_TRUE_RETURN_VAL(fb->dead, 0);
|
||||
return fb->sizes[0];
|
||||
}
|
||||
|
||||
EAPI unsigned int
|
||||
ecore_drm2_fb_stride_get(Ecore_Drm2_Fb *fb)
|
||||
{
|
||||
EINA_SAFETY_ON_NULL_RETURN_VAL(fb, 0);
|
||||
EINA_SAFETY_ON_TRUE_RETURN_VAL(fb->dead, 0);
|
||||
|
||||
return fb->strides[0];
|
||||
}
|
||||
|
||||
EAPI void
|
||||
ecore_drm2_fb_dirty(Ecore_Drm2_Fb *fb, Eina_Rectangle *rects, unsigned int count)
|
||||
{
|
||||
EINA_SAFETY_ON_NULL_RETURN(fb);
|
||||
EINA_SAFETY_ON_NULL_RETURN(rects);
|
||||
EINA_SAFETY_ON_TRUE_RETURN(fb->dead);
|
||||
|
||||
#ifdef DRM_MODE_FEATURE_DIRTYFB
|
||||
drmModeClip *clip;
|
||||
unsigned int i = 0;
|
||||
int ret;
|
||||
|
||||
clip = alloca(count * sizeof(drmModeClip));
|
||||
for (i = 0; i < count; i++)
|
||||
{
|
||||
clip[i].x1 = rects[i].x;
|
||||
clip[i].y1 = rects[i].y;
|
||||
clip[i].x2 = rects[i].w;
|
||||
clip[i].y2 = rects[i].h;
|
||||
}
|
||||
|
||||
ret = sym_drmModeDirtyFB(fb->fd, fb->id, clip, count);
|
||||
if ((ret) && (ret == -EINVAL))
|
||||
WRN("Could not mark framebuffer as dirty: %m");
|
||||
#endif
|
||||
}
|
||||
|
||||
/* perhaps output is no longer a necessary parameter for this function */
|
||||
void
|
||||
_ecore_drm2_fb_buffer_release(Ecore_Drm2_Output *output EINA_UNUSED, Ecore_Drm2_Output_State *s)
|
||||
{
|
||||
Ecore_Drm2_Fb *fb = s->fb;
|
||||
|
||||
if (fb->status_handler)
|
||||
fb->status_handler(fb, ECORE_DRM2_FB_STATUS_RELEASE, fb->status_data);
|
||||
|
||||
_ecore_drm2_fb_deref(fb);
|
||||
s->fb = NULL;
|
||||
if (_ecore_drm2_use_atomic)
|
||||
{
|
||||
if (s->atomic_req)
|
||||
sym_drmModeAtomicFree(s->atomic_req);
|
||||
s->atomic_req = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
_cb_mainloop_async_timer_del(void *data)
|
||||
{
|
||||
Ecore_Drm2_Output *output = data;
|
||||
|
||||
ecore_timer_del(output->flip_timeout);
|
||||
output->flip_timeout = NULL;
|
||||
}
|
||||
|
||||
EAPI Eina_Bool
|
||||
ecore_drm2_fb_flip_complete(Ecore_Drm2_Output *output)
|
||||
{
|
||||
Eina_Bool plane_scanout;
|
||||
Ecore_Drm2_Fb *fb;
|
||||
|
||||
EINA_SAFETY_ON_NULL_RETURN_VAL(output, EINA_FALSE);
|
||||
|
||||
if (output->flip_timeout)
|
||||
{
|
||||
// XXX: output ref++
|
||||
ecore_main_loop_thread_safe_call_async
|
||||
(_cb_mainloop_async_timer_del, output);
|
||||
}
|
||||
if (!output->pending.fb) fprintf(stderr, "XXX--XXX eeeeek pending fb is NULL so current would become null ----------------------------------\n");
|
||||
if (output->current.fb && (output->current.fb != output->pending.fb))
|
||||
_ecore_drm2_fb_buffer_release(output, &output->current);
|
||||
|
||||
output->current.fb = output->pending.fb;
|
||||
output->pending.fb = NULL;
|
||||
|
||||
if (_ecore_drm2_use_atomic)
|
||||
{
|
||||
Eina_List *l, *ll;
|
||||
Ecore_Drm2_Plane *plane;
|
||||
|
||||
output->current.atomic_req = output->pending.atomic_req;
|
||||
output->pending.atomic_req = NULL;
|
||||
|
||||
EINA_LIST_FOREACH_SAFE(output->planes, l, ll, plane)
|
||||
{
|
||||
fb = plane->fb;
|
||||
plane_scanout = plane->scanout;
|
||||
if (!plane->dead)
|
||||
{
|
||||
/* First time this plane is scanned out */
|
||||
if (!plane->scanout)
|
||||
fb->scanout_count++;
|
||||
|
||||
plane->scanout = EINA_TRUE;
|
||||
if (fb->status_handler && (fb->scanout_count == 1) &&
|
||||
(plane_scanout != plane->scanout))
|
||||
fb->status_handler(fb, ECORE_DRM2_FB_STATUS_SCANOUT_ON,
|
||||
fb->status_data);
|
||||
continue;
|
||||
}
|
||||
output->planes = eina_list_remove_list(output->planes, l);
|
||||
free(plane);
|
||||
if (!plane_scanout) continue;
|
||||
|
||||
fb->scanout_count--;
|
||||
if (fb->status_handler && (fb->scanout_count == 0))
|
||||
fb->status_handler(fb, ECORE_DRM2_FB_STATUS_SCANOUT_OFF,
|
||||
fb->status_data);
|
||||
}
|
||||
}
|
||||
|
||||
EINA_LIST_FREE(output->fbs, fb)
|
||||
_ecore_drm2_fb_deref(fb);
|
||||
output->fbs = NULL;
|
||||
|
||||
return !!output->next.fb;
|
||||
}
|
||||
|
||||
Eina_Bool
|
||||
_fb_atomic_flip_test(Ecore_Drm2_Output *output)
|
||||
{
|
||||
int ret = 0;
|
||||
Eina_List *l;
|
||||
Ecore_Drm2_Crtc_State *cstate;
|
||||
Ecore_Drm2_Plane_State *pstate;
|
||||
Ecore_Drm2_Plane *plane;
|
||||
drmModeAtomicReq *req = NULL;
|
||||
uint32_t flags = DRM_MODE_ATOMIC_NONBLOCK | DRM_MODE_ATOMIC_ALLOW_MODESET |
|
||||
DRM_MODE_ATOMIC_TEST_ONLY;
|
||||
|
||||
if (!_ecore_drm2_use_atomic) return EINA_FALSE;
|
||||
|
||||
req = sym_drmModeAtomicAlloc();
|
||||
if (!req) return EINA_FALSE;
|
||||
|
||||
sym_drmModeAtomicSetCursor(req, 0);
|
||||
|
||||
cstate = output->crtc_state;
|
||||
|
||||
ret =
|
||||
sym_drmModeAtomicAddProperty(req, cstate->obj_id, cstate->mode.id,
|
||||
cstate->mode.value);
|
||||
if (ret < 0) goto err;
|
||||
|
||||
ret =
|
||||
sym_drmModeAtomicAddProperty(req, cstate->obj_id, cstate->active.id,
|
||||
cstate->active.value);
|
||||
if (ret < 0) goto err;
|
||||
|
||||
if (cstate->background.id)
|
||||
{
|
||||
ret =
|
||||
sym_drmModeAtomicAddProperty(req, cstate->obj_id,
|
||||
cstate->background.id,
|
||||
cstate->background.value);
|
||||
if (ret < 0) goto err;
|
||||
}
|
||||
|
||||
EINA_LIST_FOREACH(output->planes, l, plane)
|
||||
{
|
||||
pstate = plane->state;
|
||||
|
||||
if (!pstate->in_use)
|
||||
{
|
||||
pstate->cid.value = 0;
|
||||
pstate->fid.value = 0;
|
||||
pstate->sw.value = 0;
|
||||
pstate->sh.value = 0;
|
||||
pstate->cx.value = 0;
|
||||
pstate->cy.value = 0;
|
||||
pstate->cw.value = 0;
|
||||
pstate->ch.value = 0;
|
||||
}
|
||||
|
||||
ret =
|
||||
sym_drmModeAtomicAddProperty(req, pstate->obj_id,
|
||||
pstate->cid.id, pstate->cid.value);
|
||||
if (ret < 0) goto err;
|
||||
|
||||
ret =
|
||||
sym_drmModeAtomicAddProperty(req, pstate->obj_id,
|
||||
pstate->fid.id, pstate->fid.value);
|
||||
if (ret < 0) goto err;
|
||||
|
||||
ret =
|
||||
sym_drmModeAtomicAddProperty(req, pstate->obj_id,
|
||||
pstate->sx.id, pstate->sx.value);
|
||||
if (ret < 0) goto err;
|
||||
|
||||
ret =
|
||||
sym_drmModeAtomicAddProperty(req, pstate->obj_id,
|
||||
pstate->sy.id, pstate->sy.value);
|
||||
if (ret < 0) goto err;
|
||||
|
||||
ret =
|
||||
sym_drmModeAtomicAddProperty(req, pstate->obj_id,
|
||||
pstate->sw.id, pstate->sw.value);
|
||||
if (ret < 0) goto err;
|
||||
|
||||
ret =
|
||||
sym_drmModeAtomicAddProperty(req, pstate->obj_id,
|
||||
pstate->sh.id, pstate->sh.value);
|
||||
if (ret < 0) goto err;
|
||||
|
||||
ret =
|
||||
sym_drmModeAtomicAddProperty(req, pstate->obj_id,
|
||||
pstate->cx.id, pstate->cx.value);
|
||||
if (ret < 0) goto err;
|
||||
|
||||
ret =
|
||||
sym_drmModeAtomicAddProperty(req, pstate->obj_id,
|
||||
pstate->cy.id, pstate->cy.value);
|
||||
if (ret < 0) goto err;
|
||||
|
||||
ret =
|
||||
sym_drmModeAtomicAddProperty(req, pstate->obj_id,
|
||||
pstate->cw.id, pstate->cw.value);
|
||||
if (ret < 0) goto err;
|
||||
|
||||
ret =
|
||||
sym_drmModeAtomicAddProperty(req, pstate->obj_id,
|
||||
pstate->ch.id, pstate->ch.value);
|
||||
if (ret < 0) goto err;
|
||||
|
||||
#if 0
|
||||
/* XXX: Disable hardware plane rotation for now as this has broken
|
||||
* recently. The break happens because of an invalid argument,
|
||||
* ie: the value being sent from pstate->rotation_map ends up being
|
||||
* incorrect for some reason. I suspect the breakage to be from
|
||||
* kernel drivers (linux 4.20.0) but have not confirmed that version */
|
||||
if ((pstate->rotation.id) &&
|
||||
(pstate->type.value == DRM_PLANE_TYPE_PRIMARY))
|
||||
{
|
||||
DBG("Plane %d Atomic Rotation: %lu",
|
||||
pstate->obj_id, pstate->rotation.value);
|
||||
ret =
|
||||
sym_drmModeAtomicAddProperty(req, pstate->obj_id,
|
||||
pstate->rotation.id,
|
||||
pstate->rotation_map[pstate->rotation.value]);
|
||||
if (ret < 0) goto err;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
ret =
|
||||
sym_drmModeAtomicCommit(output->fd, req, flags, output);
|
||||
if (ret < 0) goto err;
|
||||
|
||||
/* clear any previous request */
|
||||
if (output->prep.atomic_req)
|
||||
sym_drmModeAtomicFree(output->prep.atomic_req);
|
||||
|
||||
output->prep.atomic_req = req;
|
||||
return EINA_TRUE;
|
||||
|
||||
err:
|
||||
DBG("Failed Atomic Test: %m");
|
||||
sym_drmModeAtomicFree(req);
|
||||
|
||||
return EINA_FALSE;
|
||||
}
|
||||
|
||||
static int _fb_atomic_flip(Ecore_Drm2_Output *output);
|
||||
static int _fb_flip(Ecore_Drm2_Output *output);
|
||||
|
||||
static Eina_Bool
|
||||
_cb_flip_timeout(void *data)
|
||||
{
|
||||
Ecore_Drm2_Output *output = data;
|
||||
|
||||
output->flip_timeout = NULL;
|
||||
ERR("flip event callback timout %0.2fsec - try again", FLIP_TIMEOUT);
|
||||
if (_ecore_drm2_use_atomic) _fb_atomic_flip(output);
|
||||
else _fb_flip(output);
|
||||
return EINA_FALSE;
|
||||
}
|
||||
|
||||
static void
|
||||
_cb_mainloop_async_timer_reset(void *data)
|
||||
{
|
||||
Ecore_Drm2_Output *output = data;
|
||||
if (output->flip_timeout) ecore_timer_del(output->flip_timeout);
|
||||
output->flip_timeout = ecore_timer_add(FLIP_TIMEOUT, _cb_flip_timeout, output);
|
||||
}
|
||||
|
||||
static int
|
||||
_fb_atomic_flip(Ecore_Drm2_Output *output)
|
||||
{
|
||||
int res = 0;
|
||||
uint32_t flags =
|
||||
DRM_MODE_ATOMIC_NONBLOCK | DRM_MODE_PAGE_FLIP_EVENT |
|
||||
DRM_MODE_ATOMIC_ALLOW_MODESET;
|
||||
|
||||
if (!_ecore_drm2_use_atomic) return -1;
|
||||
|
||||
/* If we have no req yet, we're flipping to current state.
|
||||
* rebuild the current state in the prep state */
|
||||
if (!output->prep.atomic_req) _fb_atomic_flip_test(output);
|
||||
|
||||
/* Still no req is a bad situation */
|
||||
EINA_SAFETY_ON_NULL_RETURN_VAL(output->prep.atomic_req, -1);
|
||||
|
||||
// sometimes we get a EBUSY ... so try again a few times.
|
||||
int i;
|
||||
for (i = 0; i < 10; i++)
|
||||
{
|
||||
res =
|
||||
sym_drmModeAtomicCommit(output->fd, output->prep.atomic_req, flags,
|
||||
output);
|
||||
if (res == 0) break;
|
||||
else ERR("DRM atomic commit failed - retry #%i", i + 1);
|
||||
usleep(100);
|
||||
}
|
||||
|
||||
if (res < 0)
|
||||
{
|
||||
ERR("Failed Atomic Commit: %m");
|
||||
return -1;
|
||||
}
|
||||
else
|
||||
{
|
||||
// XXX: output ref++
|
||||
ecore_main_loop_thread_safe_call_async
|
||||
(_cb_mainloop_async_timer_reset, output);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
_fb_flip(Ecore_Drm2_Output *output)
|
||||
{
|
||||
Ecore_Drm2_Fb *fb;
|
||||
Eina_Bool repeat;
|
||||
int count = 0;
|
||||
int ret = 0;
|
||||
|
||||
fb = output->prep.fb;
|
||||
if (!fb)
|
||||
{
|
||||
fb = output->pending.fb;
|
||||
ERR("Trying to flip NULL fb - fallback to pending fb");
|
||||
}
|
||||
if (!fb)
|
||||
{
|
||||
ERR("Pending fb is also NULL, give up flipping");
|
||||
return ret;
|
||||
}
|
||||
|
||||
if ((!output->current.fb) ||
|
||||
(output->current.fb->strides[0] != fb->strides[0]))
|
||||
{
|
||||
ret =
|
||||
sym_drmModeSetCrtc(fb->fd, output->crtc_id, fb->id,
|
||||
0, 0, &output->conn_id, 1,
|
||||
&output->current_mode->info);
|
||||
if (ret)
|
||||
{
|
||||
ERR("Failed to set Mode %dx%d for Output %s: %m",
|
||||
output->current_mode->width, output->current_mode->height,
|
||||
output->name);
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (output->current.fb)
|
||||
_ecore_drm2_fb_buffer_release(output, &output->current);
|
||||
output->current.fb = fb;
|
||||
_ecore_drm2_fb_ref(output->current.fb);
|
||||
output->next.fb = NULL;
|
||||
/* We used to return here, but now that the ticker is fixed this
|
||||
* can leave us hanging waiting for a tick to happen forever.
|
||||
* Instead, we now fall through to the flip path to make sure
|
||||
* even this first set can cause a flip callback.
|
||||
*/
|
||||
}
|
||||
|
||||
do
|
||||
{
|
||||
static Eina_Bool bugged_about_bug = EINA_FALSE;
|
||||
repeat = EINA_FALSE;
|
||||
ret = sym_drmModePageFlip(fb->fd, output->crtc_id, fb->id,
|
||||
DRM_MODE_PAGE_FLIP_EVENT, output);
|
||||
/* Some drivers (RPI - looking at you) are broken and produce
|
||||
* flip events before they are ready for another flip, so be
|
||||
* a little robust in the face of badness and try a few times
|
||||
* until we can flip or we give up (100 tries with a yield
|
||||
* between each try). We can't expect everyone to run the
|
||||
* latest bleeding edge kernel IF a workaround is possible
|
||||
* in userspace, so do this.
|
||||
* We only report this as an ERR once since if it will
|
||||
* generate a huge amount of spam otherwise. */
|
||||
if ((ret < 0) && (errno == EBUSY))
|
||||
{
|
||||
repeat = EINA_TRUE;
|
||||
if (count == 0 && !bugged_about_bug)
|
||||
{
|
||||
ERR("Pageflip fail - EBUSY from drmModePageFlip - "
|
||||
"This is either a kernel bug or an EFL one.");
|
||||
bugged_about_bug = EINA_TRUE;
|
||||
}
|
||||
count++;
|
||||
if (count > 500)
|
||||
{
|
||||
ERR("Pageflip EBUSY for %i tries - give up", count);
|
||||
break;
|
||||
}
|
||||
usleep(100);
|
||||
}
|
||||
else
|
||||
{
|
||||
// XXX: output ref++
|
||||
ecore_main_loop_thread_safe_call_async
|
||||
(_cb_mainloop_async_timer_reset, output);
|
||||
}
|
||||
}
|
||||
while (repeat);
|
||||
|
||||
if ((ret == 0) && (count > 0))
|
||||
DBG("Pageflip finally succeeded after %i tries due to EBUSY", count);
|
||||
|
||||
if ((ret < 0) && (errno != EBUSY))
|
||||
{
|
||||
ERR("Pageflip Failed for Crtc %u on Connector %u: %m",
|
||||
output->crtc_id, output->conn_id);
|
||||
return ret;
|
||||
}
|
||||
else if (ret < 0)
|
||||
{
|
||||
output->next.fb = fb;
|
||||
_ecore_drm2_fb_ref(output->next.fb);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
EAPI int
|
||||
ecore_drm2_fb_flip(Ecore_Drm2_Fb *fb, Ecore_Drm2_Output *output)
|
||||
{
|
||||
int ret = -1;
|
||||
|
||||
EINA_SAFETY_ON_NULL_RETURN_VAL(output, -1);
|
||||
EINA_SAFETY_ON_NULL_RETURN_VAL(output->current_mode, -1);
|
||||
|
||||
if (!output->enabled) return -1;
|
||||
|
||||
if (fb) _ecore_drm2_fb_ref(fb);
|
||||
|
||||
if (output->pending.fb)
|
||||
{
|
||||
if (output->next.fb)
|
||||
_ecore_drm2_fb_buffer_release(output, &output->next);
|
||||
output->next.fb = fb;
|
||||
return 0;
|
||||
}
|
||||
if (!fb)
|
||||
{
|
||||
fb = output->next.fb;
|
||||
output->next.fb = NULL;
|
||||
}
|
||||
|
||||
/* So we can generate a tick by flipping to the current fb */
|
||||
if (!fb) fb = output->current.fb;
|
||||
|
||||
if (output->next.fb)
|
||||
_ecore_drm2_fb_buffer_release(output, &output->next);
|
||||
|
||||
/* If we don't have an fb to set by now, BAIL! */
|
||||
if (!fb) return -1;
|
||||
|
||||
output->prep.fb = fb;
|
||||
|
||||
if (_ecore_drm2_use_atomic)
|
||||
ret = _fb_atomic_flip(output);
|
||||
else
|
||||
ret = _fb_flip(output);
|
||||
|
||||
if (ret)
|
||||
{
|
||||
if (output->prep.fb != output->current.fb)
|
||||
_ecore_drm2_fb_buffer_release(output, &output->prep);
|
||||
return ret;
|
||||
}
|
||||
output->pending.fb = output->prep.fb;
|
||||
output->prep.fb = NULL;
|
||||
|
||||
if (_ecore_drm2_use_atomic)
|
||||
{
|
||||
output->pending.atomic_req = output->prep.atomic_req;
|
||||
output->prep.atomic_req = NULL;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
EAPI Eina_Bool
|
||||
ecore_drm2_fb_busy_get(Ecore_Drm2_Fb *fb)
|
||||
{
|
||||
EINA_SAFETY_ON_NULL_RETURN_VAL(fb, EINA_FALSE);
|
||||
EINA_SAFETY_ON_TRUE_RETURN_VAL(fb->dead, EINA_FALSE);
|
||||
|
||||
return !!(fb->ref - 1);
|
||||
}
|
||||
|
||||
EAPI Eina_Bool
|
||||
ecore_drm2_fb_release(Ecore_Drm2_Output *o, Eina_Bool panic)
|
||||
{
|
||||
EINA_SAFETY_ON_NULL_RETURN_VAL(o, EINA_FALSE);
|
||||
|
||||
if (o->next.fb)
|
||||
{
|
||||
_ecore_drm2_fb_buffer_release(o, &o->next);
|
||||
return EINA_TRUE;
|
||||
}
|
||||
if (!panic) return EINA_FALSE;
|
||||
|
||||
/* This has been demoted to DBG from WRN because we
|
||||
* call this function to reclaim all buffers on a
|
||||
* surface resize.
|
||||
*/
|
||||
DBG("Buffer release request when no next buffer");
|
||||
/* If we have to release these we're going to see tearing.
|
||||
* Try to reclaim in decreasing order of visual awfulness
|
||||
*/
|
||||
if (o->current.fb)
|
||||
{
|
||||
_ecore_drm2_fb_buffer_release(o, &o->current);
|
||||
return EINA_TRUE;
|
||||
}
|
||||
|
||||
if (o->pending.fb)
|
||||
{
|
||||
_ecore_drm2_fb_buffer_release(o, &o->pending);
|
||||
return EINA_TRUE;
|
||||
}
|
||||
|
||||
return EINA_FALSE;
|
||||
}
|
||||
|
||||
EAPI void *
|
||||
ecore_drm2_fb_bo_get(Ecore_Drm2_Fb *fb)
|
||||
{
|
||||
EINA_SAFETY_ON_NULL_RETURN_VAL(fb, NULL);
|
||||
EINA_SAFETY_ON_TRUE_RETURN_VAL(fb->dead, NULL);
|
||||
|
||||
return fb->gbm_bo;
|
||||
}
|
||||
|
||||
EAPI Ecore_Drm2_Fb *
|
||||
ecore_drm2_fb_dmabuf_import(Ecore_Drm2_Device *dev, int width, int height, int depth, int bpp, unsigned int format, unsigned int strides[4], int dmabuf_fd[4], int dmabuf_fd_count)
|
||||
{
|
||||
int i;
|
||||
Ecore_Drm2_Fb *fb;
|
||||
|
||||
EINA_SAFETY_ON_NULL_RETURN_VAL(dev, NULL);
|
||||
|
||||
fb = calloc(1, sizeof(Ecore_Drm2_Fb));
|
||||
if (!fb) return NULL;
|
||||
|
||||
for (i = 0; i < dmabuf_fd_count; i++)
|
||||
if (sym_drmPrimeFDToHandle(dev->fd, dmabuf_fd[i], &fb->handles[i]))
|
||||
goto fail;
|
||||
|
||||
fb->dmabuf = EINA_TRUE;
|
||||
fb->fd = dev->fd;
|
||||
fb->w = width;
|
||||
fb->h = height;
|
||||
fb->bpp = bpp;
|
||||
fb->depth = depth;
|
||||
fb->format = format;
|
||||
fb->ref = 1;
|
||||
|
||||
memcpy(&fb->strides, strides, sizeof(fb->strides));
|
||||
if (_fb2_create(fb)) return fb;
|
||||
|
||||
fail:
|
||||
free(fb);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
EAPI void
|
||||
ecore_drm2_fb_status_handler_set(Ecore_Drm2_Fb *fb, Ecore_Drm2_Fb_Status_Handler handler, void *data)
|
||||
{
|
||||
fb->status_handler = handler;
|
||||
fb->status_data = data;
|
||||
}
|
File diff suppressed because it is too large
Load Diff
|
@ -1,203 +0,0 @@
|
|||
#include "ecore_drm2_private.h"
|
||||
|
||||
static Eina_Bool
|
||||
_plane_format_supported(Ecore_Drm2_Plane_State *pstate, uint32_t format)
|
||||
{
|
||||
Eina_Bool ret = EINA_FALSE;
|
||||
unsigned int i = 0;
|
||||
|
||||
for (; i < pstate->num_formats; i++)
|
||||
{
|
||||
if (pstate->formats[i] == format)
|
||||
{
|
||||
ret = EINA_TRUE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void
|
||||
_plane_cursor_size_get(int fd, int *width, int *height)
|
||||
{
|
||||
uint64_t caps;
|
||||
int ret;
|
||||
|
||||
if (width)
|
||||
{
|
||||
*width = 64;
|
||||
ret = sym_drmGetCap(fd, DRM_CAP_CURSOR_WIDTH, &caps);
|
||||
if (ret == 0) *width = caps;
|
||||
}
|
||||
if (height)
|
||||
{
|
||||
*height = 64;
|
||||
ret = sym_drmGetCap(fd, DRM_CAP_CURSOR_HEIGHT, &caps);
|
||||
if (ret == 0) *height = caps;
|
||||
}
|
||||
}
|
||||
|
||||
EAPI Ecore_Drm2_Plane *
|
||||
ecore_drm2_plane_assign(Ecore_Drm2_Output *output, Ecore_Drm2_Fb *fb, int x, int y)
|
||||
{
|
||||
Eina_List *l;
|
||||
Ecore_Drm2_Plane *plane;
|
||||
Ecore_Drm2_Plane_State *pstate;
|
||||
|
||||
if (!_ecore_drm2_use_atomic) return NULL;
|
||||
|
||||
/* use algo based on format, size, etc to find a plane this FB can go in */
|
||||
EINA_LIST_FOREACH(output->plane_states, l, pstate)
|
||||
{
|
||||
if (pstate->in_use)
|
||||
continue;
|
||||
|
||||
/* test if this plane supports the given format */
|
||||
if (!_plane_format_supported(pstate, fb->format))
|
||||
continue;
|
||||
|
||||
if (pstate->type.value == DRM_PLANE_TYPE_CURSOR)
|
||||
{
|
||||
int cw, ch;
|
||||
|
||||
_plane_cursor_size_get(output->fd, &cw, &ch);
|
||||
|
||||
/* check that this fb can fit in cursor plane */
|
||||
if ((fb->w != cw) || (fb->h != ch))
|
||||
continue;
|
||||
|
||||
/* if we reach here, this FB can go on the cursor plane */
|
||||
goto out;
|
||||
}
|
||||
else if (pstate->type.value == DRM_PLANE_TYPE_OVERLAY)
|
||||
{
|
||||
/* there are no size checks for an overlay plane */
|
||||
goto out;
|
||||
}
|
||||
else if (pstate->type.value == DRM_PLANE_TYPE_PRIMARY)
|
||||
{
|
||||
if ((fb->w > output->current_mode->width) ||
|
||||
(fb->h > output->current_mode->height))
|
||||
continue;
|
||||
|
||||
/* if we reach here, this FB can go on the primary plane */
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
|
||||
out:
|
||||
/* create plane */
|
||||
plane = calloc(1, sizeof(Ecore_Drm2_Plane));
|
||||
if (!plane) return NULL;
|
||||
|
||||
pstate->in_use = EINA_TRUE;
|
||||
pstate->cid.value = output->crtc_id;
|
||||
pstate->fid.value = fb->id;
|
||||
plane->fb = fb;
|
||||
|
||||
pstate->sx.value = 0;
|
||||
pstate->sy.value = 0;
|
||||
pstate->sw.value = fb->w << 16;
|
||||
pstate->sh.value = fb->h << 16;
|
||||
|
||||
pstate->cx.value = x;
|
||||
pstate->cy.value = y;
|
||||
pstate->cw.value = fb->w;
|
||||
pstate->ch.value = fb->h;
|
||||
|
||||
plane->state = pstate;
|
||||
plane->type = pstate->type.value;
|
||||
plane->output = output;
|
||||
|
||||
output->planes = eina_list_append(output->planes, plane);
|
||||
|
||||
if (!_fb_atomic_flip_test(output))
|
||||
{
|
||||
output->planes = eina_list_remove(output->planes, plane);
|
||||
plane->state->in_use = EINA_FALSE;
|
||||
free(plane);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
_ecore_drm2_fb_ref(fb);
|
||||
DBG("FB %d assigned to Plane %d", fb->id, pstate->obj_id);
|
||||
|
||||
if (fb->status_handler)
|
||||
fb->status_handler(fb,
|
||||
ECORE_DRM2_FB_STATUS_PLANE_ASSIGN,
|
||||
fb->status_data);
|
||||
return plane;
|
||||
}
|
||||
|
||||
EAPI void
|
||||
ecore_drm2_plane_release(Ecore_Drm2_Plane *plane)
|
||||
{
|
||||
Ecore_Drm2_Fb *fb;
|
||||
|
||||
EINA_SAFETY_ON_NULL_RETURN(plane);
|
||||
EINA_SAFETY_ON_TRUE_RETURN(plane->dead);
|
||||
|
||||
fb = plane->fb;
|
||||
|
||||
plane->output->fbs =
|
||||
eina_list_append(plane->output->fbs, fb);
|
||||
|
||||
plane->dead = EINA_TRUE;
|
||||
plane->state->in_use = EINA_FALSE;
|
||||
_fb_atomic_flip_test(plane->output);
|
||||
|
||||
if (fb->status_handler)
|
||||
fb->status_handler(fb,
|
||||
ECORE_DRM2_FB_STATUS_PLANE_RELEASE,
|
||||
fb->status_data);
|
||||
}
|
||||
|
||||
EAPI void
|
||||
ecore_drm2_plane_destination_set(Ecore_Drm2_Plane *plane, int x, int y, int w, int h)
|
||||
{
|
||||
EINA_SAFETY_ON_NULL_RETURN(plane);
|
||||
EINA_SAFETY_ON_TRUE_RETURN(plane->dead);
|
||||
|
||||
plane->state->cx.value = x;
|
||||
plane->state->cy.value = y;
|
||||
plane->state->cw.value = w;
|
||||
plane->state->ch.value = h;
|
||||
|
||||
_fb_atomic_flip_test(plane->output);
|
||||
}
|
||||
|
||||
EAPI Eina_Bool
|
||||
ecore_drm2_plane_fb_set(Ecore_Drm2_Plane *plane, Ecore_Drm2_Fb *fb)
|
||||
{
|
||||
uint32_t fallback_id;
|
||||
|
||||
EINA_SAFETY_ON_NULL_RETURN_VAL(plane, EINA_FALSE);
|
||||
EINA_SAFETY_ON_NULL_RETURN_VAL(fb, EINA_FALSE);
|
||||
EINA_SAFETY_ON_TRUE_RETURN_VAL(plane->dead, EINA_FALSE);
|
||||
|
||||
fallback_id = plane->state->fid.value;
|
||||
plane->state->fid.value = fb->id;
|
||||
|
||||
/* Update plane state based on fb */
|
||||
plane->state->sw.value = fb->w << 16;
|
||||
plane->state->sh.value = fb->h << 16;
|
||||
plane->state->cw.value = fb->w;
|
||||
plane->state->ch.value = fb->h;
|
||||
|
||||
if (_fb_atomic_flip_test(plane->output))
|
||||
{
|
||||
_ecore_drm2_fb_ref(fb);
|
||||
|
||||
plane->output->fbs =
|
||||
eina_list_append(plane->output->fbs, plane->fb);
|
||||
|
||||
plane->fb = fb;
|
||||
return EINA_TRUE;
|
||||
}
|
||||
plane->state->fid.value = fallback_id;
|
||||
return EINA_FALSE;
|
||||
}
|
|
@ -0,0 +1,398 @@
|
|||
#include "ecore_drm2_private.h"
|
||||
|
||||
static Eina_Thread_Queue *thq = NULL;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
Eina_Thread_Queue_Msg head;
|
||||
Ecore_Drm2_Thread_Op_Code code;
|
||||
} Thread_Msg;
|
||||
|
||||
static void
|
||||
_ecore_drm2_plane_state_thread_send(Ecore_Drm2_Thread_Op_Code code)
|
||||
{
|
||||
Thread_Msg *msg;
|
||||
void *ref;
|
||||
|
||||
msg = eina_thread_queue_send(thq, sizeof(Thread_Msg), &ref);
|
||||
msg->code = code;
|
||||
eina_thread_queue_send_done(thq, ref);
|
||||
}
|
||||
|
||||
static void
|
||||
_ecore_drm2_plane_state_debug(Ecore_Drm2_Plane *plane)
|
||||
{
|
||||
DBG("Plane Atomic State Fill Complete");
|
||||
DBG("\tPlane: %d", plane->state.current->obj_id);
|
||||
DBG("\t\tCrtc: %lu", (long)plane->state.current->cid.value);
|
||||
DBG("\t\tFB: %lu", (long)plane->state.current->fid.value);
|
||||
switch (plane->state.current->type.value)
|
||||
{
|
||||
case DRM_PLANE_TYPE_OVERLAY:
|
||||
DBG("\t\tType: Overlay Plane");
|
||||
break;
|
||||
case DRM_PLANE_TYPE_PRIMARY:
|
||||
DBG("\t\tType: Primary Plane");
|
||||
break;
|
||||
case DRM_PLANE_TYPE_CURSOR:
|
||||
DBG("\t\tType: Cursor Plane");
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
DBG("\t\tZPos: %lu", (long)plane->state.current->zpos.value);
|
||||
DBG("\t\t\tMin: %lu", (long)plane->state.current->zpos.min);
|
||||
DBG("\t\t\tMax: %lu", (long)plane->state.current->zpos.max);
|
||||
}
|
||||
|
||||
static void
|
||||
_ecore_drm2_plane_state_fill(Ecore_Drm2_Plane *plane)
|
||||
{
|
||||
Ecore_Drm2_Plane_State *pstate;
|
||||
drmModeObjectPropertiesPtr oprops;
|
||||
drmModePlanePtr p;
|
||||
unsigned int i = 0;
|
||||
|
||||
plane->state.current = calloc(1, sizeof(Ecore_Drm2_Plane_State));
|
||||
if (!plane->state.current)
|
||||
{
|
||||
ERR("Could not allocate space for plane state");
|
||||
return;
|
||||
}
|
||||
|
||||
p = plane->drmPlane;
|
||||
pstate = plane->state.current;
|
||||
|
||||
pstate->obj_id = plane->id;
|
||||
pstate->mask = p->possible_crtcs;
|
||||
pstate->num_formats = p->count_formats;
|
||||
|
||||
pstate->formats = calloc(p->count_formats, sizeof(uint32_t));
|
||||
for (; i < p->count_formats; i++)
|
||||
pstate->formats[i] = p->formats[i];
|
||||
|
||||
/* try to fill get drm properties of this plane */
|
||||
oprops =
|
||||
sym_drmModeObjectGetProperties(plane->fd, pstate->obj_id,
|
||||
DRM_MODE_OBJECT_PLANE);
|
||||
if (!oprops) return;
|
||||
|
||||
/* fill atomic state */
|
||||
for (i = 0; i < oprops->count_props; i++)
|
||||
{
|
||||
drmModePropertyPtr prop;
|
||||
|
||||
prop = sym_drmModeGetProperty(plane->fd, oprops->props[i]);
|
||||
if (!prop) continue;
|
||||
|
||||
if (!strcmp(prop->name, "CRTC_ID"))
|
||||
{
|
||||
pstate->cid.id = prop->prop_id;
|
||||
pstate->cid.flags = prop->flags;
|
||||
pstate->cid.value = oprops->prop_values[i];
|
||||
}
|
||||
else if (!strcmp(prop->name, "FB_ID"))
|
||||
{
|
||||
pstate->fid.id = prop->prop_id;
|
||||
pstate->fid.flags = prop->flags;
|
||||
pstate->fid.value = oprops->prop_values[i];
|
||||
}
|
||||
else if (!strcmp(prop->name, "CRTC_X"))
|
||||
{
|
||||
pstate->cx.id = prop->prop_id;
|
||||
pstate->cx.flags = prop->flags;
|
||||
pstate->cx.value = oprops->prop_values[i];
|
||||
}
|
||||
else if (!strcmp(prop->name, "CRTC_Y"))
|
||||
{
|
||||
pstate->cy.id = prop->prop_id;
|
||||
pstate->cy.flags = prop->flags;
|
||||
pstate->cy.value = oprops->prop_values[i];
|
||||
}
|
||||
else if (!strcmp(prop->name, "CRTC_W"))
|
||||
{
|
||||
pstate->cw.id = prop->prop_id;
|
||||
pstate->cw.flags = prop->flags;
|
||||
pstate->cw.value = oprops->prop_values[i];
|
||||
}
|
||||
else if (!strcmp(prop->name, "CRTC_H"))
|
||||
{
|
||||
pstate->ch.id = prop->prop_id;
|
||||
pstate->ch.flags = prop->flags;
|
||||
pstate->ch.value = oprops->prop_values[i];
|
||||
}
|
||||
else if (!strcmp(prop->name, "SRC_X"))
|
||||
{
|
||||
pstate->sx.id = prop->prop_id;
|
||||
pstate->sx.flags = prop->flags;
|
||||
pstate->sx.value = oprops->prop_values[i];
|
||||
}
|
||||
else if (!strcmp(prop->name, "SRC_Y"))
|
||||
{
|
||||
pstate->sy.id = prop->prop_id;
|
||||
pstate->sy.flags = prop->flags;
|
||||
pstate->sy.value = oprops->prop_values[i];
|
||||
}
|
||||
else if (!strcmp(prop->name, "SRC_W"))
|
||||
{
|
||||
pstate->sw.id = prop->prop_id;
|
||||
pstate->sw.flags = prop->flags;
|
||||
pstate->sw.value = oprops->prop_values[i];
|
||||
}
|
||||
else if (!strcmp(prop->name, "SRC_H"))
|
||||
{
|
||||
pstate->sh.id = prop->prop_id;
|
||||
pstate->sh.flags = prop->flags;
|
||||
pstate->sh.value = oprops->prop_values[i];
|
||||
}
|
||||
else if (!strcmp(prop->name, "type"))
|
||||
{
|
||||
pstate->type.id = prop->prop_id;
|
||||
pstate->type.flags = prop->flags;
|
||||
pstate->type.value = oprops->prop_values[i];
|
||||
}
|
||||
else if (!strcmp(prop->name, "rotation"))
|
||||
{
|
||||
int k = 0;
|
||||
|
||||
pstate->rotation.id = prop->prop_id;
|
||||
pstate->rotation.flags = prop->flags;
|
||||
pstate->rotation.value = oprops->prop_values[i];
|
||||
|
||||
for (k = 0; k < prop->count_enums; k++)
|
||||
{
|
||||
int r = -1;
|
||||
|
||||
/* DBG("\t\t\tRotation: %s", prop->enums[k].name); */
|
||||
if (!strcmp(prop->enums[k].name, "rotate-0"))
|
||||
r = ECORE_DRM2_ROTATION_NORMAL;
|
||||
else if (!strcmp(prop->enums[k].name, "rotate-90"))
|
||||
r = ECORE_DRM2_ROTATION_90;
|
||||
else if (!strcmp(prop->enums[k].name, "rotate-180"))
|
||||
r = ECORE_DRM2_ROTATION_180;
|
||||
else if (!strcmp(prop->enums[k].name, "rotate-270"))
|
||||
r = ECORE_DRM2_ROTATION_270;
|
||||
else if (!strcmp(prop->enums[k].name, "reflect-x"))
|
||||
r = ECORE_DRM2_ROTATION_REFLECT_X;
|
||||
else if (!strcmp(prop->enums[k].name, "reflect-y"))
|
||||
r = ECORE_DRM2_ROTATION_REFLECT_Y;
|
||||
|
||||
if (r != -1)
|
||||
{
|
||||
pstate->supported_rotations |= r;
|
||||
pstate->rotation_map[ffs(r)] =
|
||||
1ULL << prop->enums[k].value;
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (!strcmp(prop->name, "zpos"))
|
||||
{
|
||||
pstate->zpos.id = prop->prop_id;
|
||||
pstate->zpos.flags = prop->flags;
|
||||
pstate->zpos.value = oprops->prop_values[i];
|
||||
if ((prop->flags & DRM_MODE_PROP_RANGE) ||
|
||||
(prop->flags & DRM_MODE_PROP_SIGNED_RANGE))
|
||||
{
|
||||
pstate->zpos.min = prop->values[0];
|
||||
pstate->zpos.max = prop->values[1];
|
||||
}
|
||||
}
|
||||
|
||||
sym_drmModeFreeProperty(prop);
|
||||
}
|
||||
|
||||
sym_drmModeFreeObjectProperties(oprops);
|
||||
|
||||
/* duplicate current state into pending so we can handle changes */
|
||||
plane->state.pending = calloc(1, sizeof(Ecore_Drm2_Plane_State));
|
||||
if (plane->state.pending)
|
||||
memcpy(plane->state.pending, plane->state.current, sizeof(Ecore_Drm2_Plane_State));
|
||||
|
||||
/* send message to thread for debug printing plane state */
|
||||
_ecore_drm2_plane_state_thread_send(ECORE_DRM2_THREAD_CODE_DEBUG);
|
||||
}
|
||||
|
||||
static void
|
||||
_ecore_drm2_plane_state_thread(void *data, Ecore_Thread *thread EINA_UNUSED)
|
||||
{
|
||||
Ecore_Drm2_Plane *plane;
|
||||
Thread_Msg *msg;
|
||||
void *ref;
|
||||
|
||||
plane = data;
|
||||
|
||||
eina_thread_name_set(eina_thread_self(), "Ecore-drm2-plane");
|
||||
|
||||
while (!ecore_thread_check(thread))
|
||||
{
|
||||
msg = eina_thread_queue_wait(thq, &ref);
|
||||
if (msg)
|
||||
{
|
||||
switch (msg->code)
|
||||
{
|
||||
case ECORE_DRM2_THREAD_CODE_FILL:
|
||||
_ecore_drm2_plane_state_fill(plane);
|
||||
break;
|
||||
case ECORE_DRM2_THREAD_CODE_DEBUG:
|
||||
_ecore_drm2_plane_state_debug(plane);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
eina_thread_queue_wait_done(thq, ref);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
_ecore_drm2_plane_state_thread_notify(void *data EINA_UNUSED, Ecore_Thread *thread EINA_UNUSED, void *msg)
|
||||
{
|
||||
free(msg);
|
||||
}
|
||||
|
||||
static Ecore_Drm2_Plane *
|
||||
_ecore_drm2_plane_create(Ecore_Drm2_Device *dev, drmModePlanePtr p, uint32_t index)
|
||||
{
|
||||
Ecore_Drm2_Plane *plane;
|
||||
|
||||
/* try to allocate space for a new plane */
|
||||
plane = calloc(1, sizeof(Ecore_Drm2_Plane));
|
||||
if (!plane)
|
||||
{
|
||||
ERR("Could not allocate space for plane");
|
||||
return EINA_FALSE;
|
||||
}
|
||||
|
||||
plane->fd = dev->fd;
|
||||
plane->id = index;
|
||||
plane->drmPlane = p;
|
||||
|
||||
/* append this plane to the list */
|
||||
dev->planes = eina_list_append(dev->planes, plane);
|
||||
|
||||
return plane;
|
||||
}
|
||||
|
||||
Eina_Bool
|
||||
_ecore_drm2_planes_create(Ecore_Drm2_Device *dev)
|
||||
{
|
||||
Ecore_Drm2_Plane *plane;
|
||||
drmModePlanePtr p;
|
||||
drmModePlaneResPtr pres;
|
||||
uint32_t i = 0;
|
||||
|
||||
/* try to get plane resources from drm */
|
||||
pres = sym_drmModeGetPlaneResources(dev->fd);
|
||||
if (!pres) return EINA_FALSE;
|
||||
|
||||
thq = eina_thread_queue_new();
|
||||
|
||||
for (; i < pres->count_planes; i++)
|
||||
{
|
||||
/* try to get this plane from drm */
|
||||
p = sym_drmModeGetPlane(dev->fd, pres->planes[i]);
|
||||
if (!p) continue;
|
||||
|
||||
/* try to create a plane */
|
||||
plane = _ecore_drm2_plane_create(dev, p, pres->planes[i]);
|
||||
if (!plane) goto err;
|
||||
|
||||
/* NB: Use an explicit thread to fill plane atomic state */
|
||||
plane->thread =
|
||||
ecore_thread_feedback_run(_ecore_drm2_plane_state_thread,
|
||||
_ecore_drm2_plane_state_thread_notify,
|
||||
NULL, NULL, plane, EINA_TRUE);
|
||||
}
|
||||
|
||||
sym_drmModeFreePlaneResources(pres);
|
||||
return EINA_TRUE;
|
||||
|
||||
err:
|
||||
eina_thread_queue_free(thq);
|
||||
thq = NULL;
|
||||
_ecore_drm2_planes_destroy(dev);
|
||||
sym_drmModeFreePlane(p);
|
||||
sym_drmModeFreePlaneResources(pres);
|
||||
return EINA_FALSE;
|
||||
}
|
||||
|
||||
void
|
||||
_ecore_drm2_planes_destroy(Ecore_Drm2_Device *dev)
|
||||
{
|
||||
Ecore_Drm2_Plane *plane;
|
||||
|
||||
EINA_LIST_FREE(dev->planes, plane)
|
||||
{
|
||||
if (plane->thread) ecore_thread_cancel(plane->thread);
|
||||
if (plane->drmPlane) sym_drmModeFreePlane(plane->drmPlane);
|
||||
free(plane->state.pending);
|
||||
free(plane->state.current);
|
||||
free(plane);
|
||||
}
|
||||
|
||||
if (thq)
|
||||
{
|
||||
eina_thread_queue_free(thq);
|
||||
thq = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
Ecore_Drm2_Plane *
|
||||
_ecore_drm2_planes_primary_find(Ecore_Drm2_Device *dev, unsigned int crtc_id)
|
||||
{
|
||||
drmModeObjectPropertiesPtr oprops;
|
||||
Ecore_Drm2_Plane *plane;
|
||||
Eina_List *l;
|
||||
unsigned int i = 0;
|
||||
|
||||
if (!dev) return NULL;
|
||||
|
||||
EINA_LIST_FOREACH(dev->planes, l, plane)
|
||||
{
|
||||
Ecore_Drm2_Plane_State *pstate;
|
||||
|
||||
pstate = plane->state.current;
|
||||
if (pstate)
|
||||
{
|
||||
if (pstate->type.value != DRM_PLANE_TYPE_PRIMARY) continue;
|
||||
if (pstate->cid.value != crtc_id) continue;
|
||||
return plane;
|
||||
}
|
||||
else
|
||||
{
|
||||
uint64_t cid = 0, type = 0;
|
||||
|
||||
/* We need to manually query plane properties here as
|
||||
* plane->state.current may not be filled yet due to threading */
|
||||
oprops =
|
||||
sym_drmModeObjectGetProperties(plane->fd,
|
||||
plane->drmPlane->plane_id,
|
||||
DRM_MODE_OBJECT_PLANE);
|
||||
if (!oprops) continue;
|
||||
|
||||
for (i = 0; i < oprops->count_props; i++)
|
||||
{
|
||||
drmModePropertyPtr prop;
|
||||
|
||||
prop = sym_drmModeGetProperty(plane->fd, oprops->props[i]);
|
||||
if (!prop) continue;
|
||||
|
||||
if (!strcmp(prop->name, "CRTC_ID"))
|
||||
cid = oprops->prop_values[i];
|
||||
else if (!strcmp(prop->name, "type"))
|
||||
type = oprops->prop_values[i];
|
||||
|
||||
sym_drmModeFreeProperty(prop);
|
||||
}
|
||||
|
||||
sym_drmModeFreeObjectProperties(oprops);
|
||||
|
||||
if (type != DRM_PLANE_TYPE_PRIMARY) continue;
|
||||
if (cid != crtc_id) continue;
|
||||
|
||||
return plane;
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
|
@ -5,63 +5,107 @@
|
|||
# include "config.h"
|
||||
# endif
|
||||
|
||||
# include "Ecore.h"
|
||||
# include "ecore_private.h"
|
||||
# include "Eeze.h"
|
||||
# include "Elput.h"
|
||||
# include <Ecore_Drm2.h>
|
||||
|
||||
/* include system headers */
|
||||
# include <unistd.h>
|
||||
# include <strings.h>
|
||||
# include <sys/mman.h>
|
||||
# include <fcntl.h>
|
||||
# include <ctype.h>
|
||||
|
||||
# include <sys/ioctl.h>
|
||||
# include <dlfcn.h>
|
||||
|
||||
/* include drm headers */
|
||||
# include <drm.h>
|
||||
# include <drm_mode.h>
|
||||
# include <drm_fourcc.h>
|
||||
# include <xf86drm.h>
|
||||
# include <xf86drmMode.h>
|
||||
|
||||
#ifndef DRM2_NODEFS
|
||||
/* include needed EFL headers */
|
||||
# include "Ecore.h"
|
||||
# include "ecore_private.h"
|
||||
# include "Eeze.h"
|
||||
# include "Elput.h"
|
||||
# include <Ecore_Drm2.h>
|
||||
|
||||
/* define necessary vars/macros for ecore_drm2 log domain */
|
||||
extern int _ecore_drm2_log_dom;
|
||||
extern Eina_Bool _ecore_drm2_use_atomic;
|
||||
|
||||
# ifdef ECORE_DRM2_DEFAULT_LOG_COLOR
|
||||
# undef ECORE_DRM2_DEFAULT_LOG_COLOR
|
||||
# endif
|
||||
# define ECORE_DRM2_DEFAULT_LOG_COLOR EINA_COLOR_BLUE
|
||||
|
||||
# ifdef ERR
|
||||
# undef ERR
|
||||
# ifdef INF
|
||||
# undef INF
|
||||
# endif
|
||||
# define ERR(...) EINA_LOG_DOM_ERR(_ecore_drm2_log_dom, __VA_ARGS__)
|
||||
# define INF(...) EINA_LOG_DOM_INFO(_ecore_drm2_log_dom, __VA_ARGS__)
|
||||
|
||||
# ifdef DBG
|
||||
# undef DBG
|
||||
# endif
|
||||
# define DBG(...) EINA_LOG_DOM_DBG(_ecore_drm2_log_dom, __VA_ARGS__)
|
||||
|
||||
# ifdef INF
|
||||
# undef INF
|
||||
# endif
|
||||
# define INF(...) EINA_LOG_DOM_INFO(_ecore_drm2_log_dom, __VA_ARGS__)
|
||||
|
||||
# ifdef WRN
|
||||
# undef WRN
|
||||
# endif
|
||||
# define WRN(...) EINA_LOG_DOM_WARN(_ecore_drm2_log_dom, __VA_ARGS__)
|
||||
|
||||
# ifdef ERR
|
||||
# undef ERR
|
||||
# endif
|
||||
# define ERR(...) EINA_LOG_DOM_ERR(_ecore_drm2_log_dom, __VA_ARGS__)
|
||||
|
||||
# ifdef CRIT
|
||||
# undef CRIT
|
||||
# endif
|
||||
# define CRIT(...) EINA_LOG_DOM_CRIT(_ecore_drm2_log_dom, __VA_ARGS__)
|
||||
#endif
|
||||
|
||||
typedef struct _Ecore_Drm2_Atomic_State Ecore_Drm2_Atomic_State;
|
||||
/* internal structures & enums (not exposed) */
|
||||
typedef enum _Ecore_Drm2_Backlight_Type
|
||||
{
|
||||
ECORE_DRM2_BACKLIGHT_RAW,
|
||||
ECORE_DRM2_BACKLIGHT_PLATFORM,
|
||||
ECORE_DRM2_BACKLIGHT_FIRMWARE
|
||||
} Ecore_Drm2_Backlight_Type;
|
||||
|
||||
typedef enum _Ecore_Drm2_Thread_Op_Code
|
||||
{
|
||||
ECORE_DRM2_THREAD_CODE_FILL,
|
||||
ECORE_DRM2_THREAD_CODE_DEBUG
|
||||
} Ecore_Drm2_Thread_Op_Code;
|
||||
|
||||
typedef enum _Ecore_Drm2_Connector_State_Changes
|
||||
{
|
||||
ECORE_DRM2_CONNECTOR_STATE_CRTC = (1 << 0),
|
||||
ECORE_DRM2_CONNECTOR_STATE_DPMS = (1 << 1),
|
||||
ECORE_DRM2_CONNECTOR_STATE_ASPECT = (1 << 2),
|
||||
ECORE_DRM2_CONNECTOR_STATE_SCALING = (1 << 3),
|
||||
} Ecore_Drm2_Connector_State_Changes;
|
||||
|
||||
typedef enum _Ecore_Drm2_Crtc_State_Changes
|
||||
{
|
||||
ECORE_DRM2_CRTC_STATE_ACTIVE = (1 << 0),
|
||||
ECORE_DRM2_CRTC_STATE_MODE = (1 << 1),
|
||||
} Ecore_Drm2_Crtc_State_Changes;
|
||||
|
||||
typedef enum _Ecore_Drm2_Plane_State_Changes
|
||||
{
|
||||
ECORE_DRM2_PLANE_STATE_CID = (1 << 0),
|
||||
ECORE_DRM2_PLANE_STATE_FID = (1 << 1),
|
||||
ECORE_DRM2_PLANE_STATE_ROTATION = (1 << 2),
|
||||
} Ecore_Drm2_Plane_State_Changes;
|
||||
|
||||
typedef enum _Ecore_Drm2_Display_State_Changes
|
||||
{
|
||||
ECORE_DRM2_DISPLAY_STATE_GAMMA = (1 << 0),
|
||||
ECORE_DRM2_DISPLAY_STATE_ROTATION = (1 << 1),
|
||||
ECORE_DRM2_DISPLAY_STATE_BACKLIGHT = (1 << 2),
|
||||
ECORE_DRM2_DISPLAY_STATE_MODE = (1 << 3),
|
||||
ECORE_DRM2_DISPLAY_STATE_PRIMARY = (1 << 4),
|
||||
ECORE_DRM2_DISPLAY_STATE_ENABLED = (1 << 5),
|
||||
ECORE_DRM2_DISPLAY_STATE_POSITION = (1 << 6),
|
||||
} Ecore_Drm2_Display_State_Changes;
|
||||
|
||||
typedef struct _Ecore_Drm2_Atomic_Blob
|
||||
{
|
||||
|
@ -72,152 +116,137 @@ typedef struct _Ecore_Drm2_Atomic_Blob
|
|||
|
||||
typedef struct _Ecore_Drm2_Atomic_Property
|
||||
{
|
||||
uint32_t id;
|
||||
uint32_t id, flags;
|
||||
uint64_t value;
|
||||
} Ecore_Drm2_Atomic_Property;
|
||||
|
||||
typedef struct _Ecore_Drm2_Atomic_Range
|
||||
{
|
||||
uint32_t id, flags;
|
||||
uint64_t min, max, value;
|
||||
} Ecore_Drm2_Atomic_Range;
|
||||
|
||||
typedef struct _Ecore_Drm2_Connector_State
|
||||
{
|
||||
uint32_t obj_id;
|
||||
uint32_t obj_id, changes;
|
||||
Ecore_Drm2_Atomic_Property crtc;
|
||||
Ecore_Drm2_Atomic_Property dpms;
|
||||
Ecore_Drm2_Atomic_Property aspect;
|
||||
Ecore_Drm2_Atomic_Property scaling;
|
||||
Ecore_Drm2_Atomic_Blob edid;
|
||||
|
||||
/* TODO ?? */
|
||||
/* Ecore_Drm2_Atomic_Property link-status; */
|
||||
/* Ecore_Drm2_Atomic_Property non-desktop; */
|
||||
/* Ecore_Drm2_Atomic_Property TILE; */
|
||||
/* Ecore_Drm2_Atomic_Property underscan; */
|
||||
/* Ecore_Drm2_Atomic_Property underscan hborder; */
|
||||
/* Ecore_Drm2_Atomic_Property underscan vborder; */
|
||||
/* Ecore_Drm2_Atomic_Property max bpc; */
|
||||
/* Ecore_Drm2_Atomic_Property HDR_OUTPUT_METADATA; */
|
||||
/* Ecore_Drm2_Atomic_Property vrr_capable; */
|
||||
/* Ecore_Drm2_Atomic_Property Content Protection; */
|
||||
/* Ecore_Drm2_Atomic_Property HDCP Content Type; */
|
||||
/* Ecore_Drm2_Atomic_Property subconnector; */
|
||||
/* Ecore_Drm2_Atomic_Property panel orientation; */
|
||||
} Ecore_Drm2_Connector_State;
|
||||
|
||||
typedef struct _Ecore_Drm2_Crtc_State
|
||||
{
|
||||
uint32_t obj_id;
|
||||
int index;
|
||||
uint32_t obj_id, changes;
|
||||
/* int index; */
|
||||
Ecore_Drm2_Atomic_Property active;
|
||||
Ecore_Drm2_Atomic_Property background;
|
||||
Ecore_Drm2_Atomic_Blob mode;
|
||||
|
||||
/* TODO ?? */
|
||||
/* Ecore_Drm2_Atomic_Property background; */
|
||||
/* Ecore_Drm2_Atomic_Property OUT_FENCE_PTR; */
|
||||
/* Ecore_Drm2_Atomic_Property VRR_ENABLED; */
|
||||
/* Ecore_Drm2_Atomic_Property DEGAMMA_LUT; */
|
||||
/* Ecore_Drm2_Atomic_Property DEGAMMA_LUT_SIZE; */
|
||||
/* Ecore_Drm2_Atomic_Property CTM; */
|
||||
/* Ecore_Drm2_Atomic_Property GAMMA_LUT; */
|
||||
/* Ecore_Drm2_Atomic_Property GAMMA_LUT_SIZE; */
|
||||
} Ecore_Drm2_Crtc_State;
|
||||
|
||||
typedef struct _Ecore_Drm2_Plane_State
|
||||
{
|
||||
uint32_t obj_id, mask;
|
||||
uint32_t obj_id, mask, changes;
|
||||
uint32_t num_formats, *formats;
|
||||
|
||||
Ecore_Drm2_Atomic_Property type;
|
||||
Ecore_Drm2_Atomic_Property cid, fid;
|
||||
Ecore_Drm2_Atomic_Property sx, sy, sw, sh;
|
||||
Ecore_Drm2_Atomic_Property cx, cy, cw, ch;
|
||||
Ecore_Drm2_Atomic_Property rotation;
|
||||
Ecore_Drm2_Atomic_Range zpos;
|
||||
|
||||
/* these are not part of an atomic state, but we store these here
|
||||
/* TODO ?? */
|
||||
/* Ecore_Drm2_Atomic_Property IN_FENCE_FD; */
|
||||
/* Ecore_Drm2_Atomic_Property IN_FORMATS; */
|
||||
/* Ecore_Drm2_Atomic_Property COLOR_ENCODING; */
|
||||
/* Ecore_Drm2_Atomic_Property COLOR_RANGE; */
|
||||
/* Ecore_Drm2_Atomic_Blob FB_DAMAGE_CLIPS; */
|
||||
|
||||
/* NB: these are not part of an atomic state, but we store these here
|
||||
* so that we do not have to refetch properties when iterating planes */
|
||||
uint32_t rotation_map[6];
|
||||
uint32_t supported_rotations;
|
||||
|
||||
uint32_t num_formats;
|
||||
uint32_t *formats;
|
||||
|
||||
Eina_Bool in_use;
|
||||
Eina_Bool in_use : 1;
|
||||
} Ecore_Drm2_Plane_State;
|
||||
|
||||
struct _Ecore_Drm2_Atomic_State
|
||||
typedef struct _Ecore_Drm2_Display_State
|
||||
{
|
||||
int crtcs, conns, planes;
|
||||
Ecore_Drm2_Crtc_State *crtc_states;
|
||||
Ecore_Drm2_Connector_State *conn_states;
|
||||
Ecore_Drm2_Plane_State *plane_states;
|
||||
};
|
||||
uint32_t changes;
|
||||
|
||||
# ifndef DRM_CAP_CURSOR_WIDTH
|
||||
# define DRM_CAP_CURSOR_WIDTH 0x8
|
||||
# endif
|
||||
int x, y;
|
||||
|
||||
# ifndef DRM_CAP_CURSOR_HEIGHT
|
||||
# define DRM_CAP_CURSOR_HEIGHT 0x9
|
||||
# endif
|
||||
uint16_t gamma;
|
||||
uint64_t rotation;
|
||||
double backlight;
|
||||
|
||||
typedef enum _Ecore_Drm2_Backlight_Type
|
||||
{
|
||||
ECORE_DRM2_BACKLIGHT_RAW,
|
||||
ECORE_DRM2_BACKLIGHT_PLATFORM,
|
||||
ECORE_DRM2_BACKLIGHT_FIRMWARE
|
||||
} Ecore_Drm2_Backlight_Type;
|
||||
Ecore_Drm2_Display_Mode *mode;
|
||||
|
||||
typedef enum _Ecore_Drm2_Transform
|
||||
{
|
||||
ECORE_DRM2_TRANSFORM_NORMAL,
|
||||
ECORE_DRM2_TRANSFORM_90,
|
||||
ECORE_DRM2_TRANSFORM_180,
|
||||
ECORE_DRM2_TRANSFORM_270,
|
||||
ECORE_DRM2_TRANSFORM_FLIPPED,
|
||||
ECORE_DRM2_TRANSFORM_FLIPPED_90,
|
||||
ECORE_DRM2_TRANSFORM_FLIPPED_180,
|
||||
ECORE_DRM2_TRANSFORM_FLIPPED_270
|
||||
} Ecore_Drm2_Transform;
|
||||
|
||||
struct _Ecore_Drm2_Fb
|
||||
{
|
||||
int fd;
|
||||
int w, h;
|
||||
int depth, bpp;
|
||||
short ref;
|
||||
int scanout_count;
|
||||
uint32_t id, handles[4];
|
||||
uint32_t strides[4], sizes[4];
|
||||
uint32_t format;
|
||||
|
||||
void *gbm_bo;
|
||||
void *mmap;
|
||||
|
||||
Ecore_Drm2_Fb_Status_Handler status_handler;
|
||||
void *status_data;
|
||||
|
||||
Eina_Bool gbm : 1;
|
||||
Eina_Bool dmabuf : 1;
|
||||
Eina_Bool dead : 1;
|
||||
};
|
||||
Eina_Bool primary : 1;
|
||||
Eina_Bool enabled : 1;
|
||||
} Ecore_Drm2_Display_State;
|
||||
|
||||
/* opaque API structures */
|
||||
struct _Ecore_Drm2_Plane
|
||||
{
|
||||
int type;
|
||||
Ecore_Drm2_Plane_State *state;
|
||||
Ecore_Drm2_Output *output;
|
||||
Ecore_Drm2_Fb *fb;
|
||||
Eina_Bool dead;
|
||||
Eina_Bool scanout;
|
||||
int fd;
|
||||
uint32_t id;
|
||||
|
||||
drmModePlanePtr drmPlane;
|
||||
|
||||
struct
|
||||
{
|
||||
Ecore_Drm2_Plane_State *current;
|
||||
Ecore_Drm2_Plane_State *pending;
|
||||
} state;
|
||||
|
||||
Ecore_Thread *thread;
|
||||
};
|
||||
|
||||
struct _Ecore_Drm2_Output_Mode
|
||||
struct _Ecore_Drm2_Display_Mode
|
||||
{
|
||||
uint32_t id;
|
||||
uint32_t flags;
|
||||
uint32_t flags, refresh;
|
||||
int32_t width, height;
|
||||
uint32_t refresh;
|
||||
drmModeModeInfo info;
|
||||
};
|
||||
|
||||
/* A half step - we still keep an fb for the canvas
|
||||
* and an atomic_req for all atomic state (including
|
||||
* the canvas fb).
|
||||
* The non atomic code only uses the canvas fb.
|
||||
*/
|
||||
typedef struct _Ecore_Drm2_Output_State
|
||||
struct _Ecore_Drm2_Display
|
||||
{
|
||||
Ecore_Drm2_Fb *fb;
|
||||
drmModeAtomicReq *atomic_req;
|
||||
} Ecore_Drm2_Output_State;
|
||||
|
||||
struct _Ecore_Drm2_Output
|
||||
{
|
||||
Eina_Stringshare *name;
|
||||
Eina_Stringshare *make, *model, *serial;
|
||||
|
||||
int fd;
|
||||
int pipe;
|
||||
int x, y, w, h, pw, ph;
|
||||
int rotation;
|
||||
|
||||
long fallback_sec, fallback_usec;
|
||||
/* int fd; */
|
||||
int x, y, w, h;
|
||||
int pw, ph; // physical dimensions
|
||||
Eina_Stringshare *name, *make, *model, *serial;
|
||||
|
||||
uint32_t subpixel;
|
||||
uint32_t crtc_id, conn_id, conn_type;
|
||||
uint32_t scale;
|
||||
uint16_t gamma;
|
||||
|
||||
/* uint32_t supported_rotations; */
|
||||
|
||||
struct
|
||||
{
|
||||
|
@ -225,13 +254,12 @@ struct _Ecore_Drm2_Output
|
|||
char monitor[13];
|
||||
char pnp[5];
|
||||
char serial[13];
|
||||
unsigned char *blob; // unused when doing atomic
|
||||
} edid;
|
||||
|
||||
struct
|
||||
{
|
||||
const char *path;
|
||||
double value, max;
|
||||
double max;
|
||||
Ecore_Drm2_Backlight_Type type;
|
||||
} backlight;
|
||||
|
||||
|
@ -241,38 +269,59 @@ struct _Ecore_Drm2_Output
|
|||
Ecore_Drm2_Relative_Mode mode;
|
||||
} relative;
|
||||
|
||||
drmModeCrtcPtr ocrtc;
|
||||
struct
|
||||
{
|
||||
Ecore_Drm2_Display_State *current;
|
||||
Ecore_Drm2_Display_State *pending;
|
||||
} state;
|
||||
|
||||
/* prep is for state we're preparing and have never
|
||||
* attempted to commit */
|
||||
Ecore_Drm2_Output_State prep;
|
||||
Ecore_Drm2_Device *dev;
|
||||
Ecore_Drm2_Crtc *crtc;
|
||||
Ecore_Drm2_Connector *conn;
|
||||
|
||||
Ecore_Drm2_Output_State current, next, pending;
|
||||
|
||||
Eina_Matrix4 matrix, inverse;
|
||||
Ecore_Drm2_Transform transform;
|
||||
|
||||
/* unused when doing atomic */
|
||||
drmModePropertyPtr dpms;
|
||||
|
||||
Ecore_Timer *flip_timeout;
|
||||
|
||||
Ecore_Drm2_Output_Mode *current_mode;
|
||||
Eina_List *modes;
|
||||
|
||||
void *user_data;
|
||||
|
||||
Ecore_Drm2_Crtc_State *crtc_state;
|
||||
Ecore_Drm2_Connector_State *conn_state;
|
||||
|
||||
Eina_List *plane_states;
|
||||
Eina_List *planes;
|
||||
Eina_List *fbs;
|
||||
Ecore_Thread *thread;
|
||||
|
||||
Eina_Bool connected : 1;
|
||||
Eina_Bool primary : 1;
|
||||
Eina_Bool cloned : 1;
|
||||
Eina_Bool enabled : 1;
|
||||
};
|
||||
|
||||
struct _Ecore_Drm2_Connector
|
||||
{
|
||||
uint32_t id;
|
||||
uint32_t type;
|
||||
int fd;
|
||||
|
||||
drmModeConnector *drmConn;
|
||||
|
||||
struct
|
||||
{
|
||||
Ecore_Drm2_Connector_State *current;
|
||||
Ecore_Drm2_Connector_State *pending;
|
||||
} state;
|
||||
|
||||
Ecore_Thread *thread;
|
||||
|
||||
Eina_Bool writeback : 1;
|
||||
};
|
||||
|
||||
struct _Ecore_Drm2_Crtc
|
||||
{
|
||||
uint32_t id;
|
||||
uint32_t pipe;
|
||||
int fd;
|
||||
|
||||
drmModeCrtcPtr drmCrtc;
|
||||
|
||||
/* TODO: store FBs */
|
||||
|
||||
struct
|
||||
{
|
||||
Ecore_Drm2_Crtc_State *current;
|
||||
Ecore_Drm2_Crtc_State *pending;
|
||||
} state;
|
||||
|
||||
Ecore_Thread *thread;
|
||||
};
|
||||
|
||||
struct _Ecore_Drm2_Device
|
||||
|
@ -280,77 +329,67 @@ struct _Ecore_Drm2_Device
|
|||
Elput_Manager *em;
|
||||
|
||||
int fd;
|
||||
const char *path;
|
||||
|
||||
int num_crtcs;
|
||||
uint32_t *crtcs;
|
||||
|
||||
struct
|
||||
{
|
||||
uint32_t width, height;
|
||||
} min, max;
|
||||
int clock_id;
|
||||
|
||||
struct
|
||||
{
|
||||
int width, height;
|
||||
} cursor;
|
||||
|
||||
Eeze_Udev_Watch *watch;
|
||||
Ecore_Event_Handler *active_hdlr;
|
||||
Ecore_Event_Handler *device_change_hdlr;
|
||||
Ecore_Event_Handler *session_hdlr;
|
||||
Ecore_Event_Handler *device_hdlr;
|
||||
|
||||
Ecore_Drm2_Atomic_State *state;
|
||||
Eina_List *crtcs;
|
||||
Eina_List *conns;
|
||||
Eina_List *displays;
|
||||
Eina_List *planes;
|
||||
|
||||
Eina_List *outputs;
|
||||
Eina_Bool atomic : 1;
|
||||
/* Eina_Bool gbm_mods : 1; */
|
||||
Eina_Bool aspect_ratio : 1;
|
||||
};
|
||||
|
||||
Eina_Bool _fb_atomic_flip_test(Ecore_Drm2_Output *output);
|
||||
void _ecore_drm2_fb_ref(Ecore_Drm2_Fb *);
|
||||
void _ecore_drm2_fb_deref(Ecore_Drm2_Fb *);
|
||||
void _ecore_drm2_fb_buffer_release(Ecore_Drm2_Output *output, Ecore_Drm2_Output_State *s);
|
||||
/* internal function prototypes */
|
||||
Eina_Bool _ecore_drm2_crtcs_create(Ecore_Drm2_Device *dev);
|
||||
void _ecore_drm2_crtcs_destroy(Ecore_Drm2_Device *dev);
|
||||
|
||||
/* extern int (*sym_drmClose)(int fd); */
|
||||
extern int (*sym_drmWaitVBlank)(int fd, drmVBlank *vbl);
|
||||
extern int (*sym_drmHandleEvent)(int fd, drmEventContext *evctx);
|
||||
extern void *(*sym_drmGetVersion)(int fd);
|
||||
extern void (*sym_drmFreeVersion)(void *drmver);
|
||||
Eina_Bool _ecore_drm2_connectors_create(Ecore_Drm2_Device *dev);
|
||||
void _ecore_drm2_connectors_destroy(Ecore_Drm2_Device *dev);
|
||||
|
||||
Eina_Bool _ecore_drm2_displays_create(Ecore_Drm2_Device *dev);
|
||||
void _ecore_drm2_displays_destroy(Ecore_Drm2_Device *dev);
|
||||
|
||||
Eina_Bool _ecore_drm2_planes_create(Ecore_Drm2_Device *dev);
|
||||
void _ecore_drm2_planes_destroy(Ecore_Drm2_Device *dev);
|
||||
Ecore_Drm2_Plane *_ecore_drm2_planes_primary_find(Ecore_Drm2_Device *dev, unsigned int crtc_id);
|
||||
|
||||
/* external drm function prototypes (for dlopen) */
|
||||
extern void *(*sym_drmModeGetResources)(int fd);
|
||||
extern void (*sym_drmModeFreeResources)(drmModeResPtr ptr);
|
||||
extern int (*sym_drmGetCap)(int fd, uint64_t capability, uint64_t *value);
|
||||
extern int (*sym_drmSetClientCap)(int fd, uint64_t capability, uint64_t value);
|
||||
extern void *(*sym_drmModeGetProperty)(int fd, uint32_t propertyId);
|
||||
extern void (*sym_drmModeFreeProperty)(drmModePropertyPtr ptr);
|
||||
extern void *(*sym_drmModeGetPropertyBlob)(int fd, uint32_t blob_id);
|
||||
extern void (*sym_drmModeFreePropertyBlob)(drmModePropertyBlobPtr ptr);
|
||||
extern int (*sym_drmModeCreatePropertyBlob)(int fd, const void *data, size_t size, uint32_t *id);
|
||||
extern int (*sym_drmModeDestroyPropertyBlob)(int fd, uint32_t id);
|
||||
extern int (*sym_drmIoctl)(int fd, unsigned long request, void *arg);
|
||||
extern void *(*sym_drmModeObjectGetProperties)(int fd, uint32_t object_id, uint32_t object_type);
|
||||
extern void (*sym_drmModeFreeObjectProperties)(drmModeObjectPropertiesPtr ptr);
|
||||
extern int (*sym_drmModeCreatePropertyBlob)(int fd, const void *data, size_t size, uint32_t *id);
|
||||
extern void *(*sym_drmModeGetPlaneResources)(int fd);
|
||||
extern void (*sym_drmModeFreePlaneResources)(drmModePlaneResPtr ptr);
|
||||
extern void *(*sym_drmModeGetPlane)(int fd, uint32_t plane_id);
|
||||
extern void (*sym_drmModeFreePlane)(drmModePlanePtr ptr);
|
||||
extern void *(*sym_drmModeGetConnector)(int fd, uint32_t connectorId);
|
||||
extern void (*sym_drmModeFreeConnector)(drmModeConnectorPtr ptr);
|
||||
extern void *(*sym_drmModeGetEncoder)(int fd, uint32_t encoder_id);
|
||||
extern void (*sym_drmModeFreeEncoder)(drmModeEncoderPtr ptr);
|
||||
extern void *(*sym_drmModeGetCrtc)(int fd, uint32_t crtcId);
|
||||
extern void (*sym_drmModeFreeCrtc)(drmModeCrtcPtr ptr);
|
||||
extern void *(*sym_drmModeAtomicAlloc)(void);
|
||||
extern void (*sym_drmModeAtomicFree)(drmModeAtomicReqPtr req);
|
||||
extern int (*sym_drmModeAtomicAddProperty)(drmModeAtomicReqPtr req, uint32_t object_id, uint32_t property_id, uint64_t value);
|
||||
extern int (*sym_drmModeAtomicCommit)(int fd, drmModeAtomicReqPtr req, uint32_t flags, void *user_data);
|
||||
extern void (*sym_drmModeAtomicSetCursor)(drmModeAtomicReqPtr req, int cursor);
|
||||
extern int (*sym_drmModeAtomicMerge)(drmModeAtomicReqPtr base, drmModeAtomicReqPtr augment);
|
||||
extern void *(*sym_drmModeGetEncoder)(int fd, uint32_t encoder_id);
|
||||
extern void (*sym_drmModeFreeEncoder)(drmModeEncoderPtr ptr);
|
||||
extern void *(*sym_drmModeGetCrtc)(int fd, uint32_t crtcId);
|
||||
extern void (*sym_drmModeFreeCrtc)(drmModeCrtcPtr ptr);
|
||||
extern int (*sym_drmModeSetCrtc)(int fd, uint32_t crtcId, uint32_t bufferId, uint32_t x, uint32_t y, uint32_t *connectors, int count, drmModeModeInfoPtr mode);
|
||||
extern void *(*sym_drmModeGetResources)(int fd);
|
||||
extern void (*sym_drmModeFreeResources)(drmModeResPtr ptr);
|
||||
extern void *(*sym_drmModeGetConnector)(int fd, uint32_t connectorId);
|
||||
extern void (*sym_drmModeFreeConnector)(drmModeConnectorPtr ptr);
|
||||
extern int (*sym_drmModeConnectorSetProperty)(int fd, uint32_t connector_id, uint32_t property_id, uint64_t value);
|
||||
extern int (*sym_drmGetCap)(int fd, uint64_t capability, uint64_t *value);
|
||||
extern int (*sym_drmSetClientCap)(int fd, uint64_t capability, uint64_t value);
|
||||
extern void *(*sym_drmModeGetPlaneResources)(int fd);
|
||||
extern void (*sym_drmModeFreePlaneResources)(drmModePlaneResPtr ptr);
|
||||
extern void *(*sym_drmModeGetPlane)(int fd, uint32_t plane_id);
|
||||
extern void (*sym_drmModeFreePlane)(drmModePlanePtr ptr);
|
||||
extern int (*sym_drmModeAddFB)(int fd, uint32_t width, uint32_t height, uint8_t depth, uint8_t bpp, uint32_t pitch, uint32_t bo_handle, uint32_t *buf_id);
|
||||
extern int (*sym_drmModeAddFB2)(int fd, uint32_t width, uint32_t height, uint32_t pixel_format, uint32_t bo_handles[4], uint32_t pitches[4], uint32_t offsets[4], uint32_t *buf_id, uint32_t flags);
|
||||
extern int (*sym_drmModeRmFB)(int fd, uint32_t bufferId);
|
||||
extern int (*sym_drmModePageFlip)(int fd, uint32_t crtc_id, uint32_t fb_id, uint32_t flags, void *user_data);
|
||||
extern int (*sym_drmModeDirtyFB)(int fd, uint32_t bufferId, drmModeClipPtr clips, uint32_t num_clips);
|
||||
extern int (*sym_drmModeCrtcSetGamma)(int fd, uint32_t crtc_id, uint32_t size, uint16_t *red, uint16_t *green, uint16_t *blue);
|
||||
extern int (*sym_drmPrimeFDToHandle)(int fd, int prime_fd, uint32_t *handle);
|
||||
|
||||
#endif
|
||||
|
|
|
@ -7,9 +7,10 @@ ecore_drm2_header_src = [
|
|||
]
|
||||
|
||||
ecore_drm2_src = files([
|
||||
'ecore_drm2_plane.c',
|
||||
'ecore_drm2_fb.c',
|
||||
'ecore_drm2_outputs.c',
|
||||
'ecore_drm2_displays.c',
|
||||
'ecore_drm2_connectors.c',
|
||||
'ecore_drm2_planes.c',
|
||||
'ecore_drm2_crtcs.c',
|
||||
'ecore_drm2_device.c',
|
||||
'ecore_drm2.c',
|
||||
'ecore_drm2_private.h'
|
||||
|
|
|
@ -467,7 +467,7 @@ ecore_x_root_screen_barriers_set(Ecore_X_Rectangle *screens, int num)
|
|||
Region reg, reg2, reg3;
|
||||
Window rwin, cwin;
|
||||
int rx, ry, wx, wy;
|
||||
int i, j;
|
||||
int i;
|
||||
int closest_dist, dist;
|
||||
int sx, sy, dx, dy;
|
||||
unsigned int mask;
|
||||
|
@ -537,50 +537,48 @@ ecore_x_root_screen_barriers_set(Ecore_X_Rectangle *screens, int num)
|
|||
bar_alloc = 0;
|
||||
if ((!screens) || (num <= 0)) return;
|
||||
|
||||
// set up new ones given the screen list given
|
||||
// new region
|
||||
reg = XCreateRegion();
|
||||
// add each screen rect + 1 pixel around it to reg
|
||||
for (i = 0; i < num; i++)
|
||||
{
|
||||
XRectangle xrect;
|
||||
|
||||
reg = XCreateRegion();
|
||||
reg2 = XCreateRegion();
|
||||
xrect.x = screens[i].x - 1;
|
||||
xrect.y = screens[i].y - 1;
|
||||
xrect.width = screens[i].width + 2;
|
||||
xrect.x = screens[i].x - 1;
|
||||
xrect.y = screens[i].y - 1;
|
||||
xrect.width = screens[i].width + 2;
|
||||
xrect.height = screens[i].height + 2;
|
||||
XUnionRectWithRegion(&xrect, reg, reg2);
|
||||
XDestroyRegion(reg);
|
||||
reg = reg2;
|
||||
}
|
||||
// del the content of each screen from the above
|
||||
for (i = 0; i < num; i++)
|
||||
{
|
||||
XRectangle xrect;
|
||||
|
||||
// reg == screen i + 1 pixel surrounding it
|
||||
for (j = 0; j < num; j++)
|
||||
{
|
||||
// create a region representing screen j
|
||||
reg2 = XCreateRegion();
|
||||
reg3 = XCreateRegion();
|
||||
xrect.x = screens[j].x;
|
||||
xrect.y = screens[j].y;
|
||||
xrect.width = screens[j].width;
|
||||
xrect.height = screens[j].height;
|
||||
XUnionRectWithRegion(&xrect, reg2, reg3);
|
||||
XDestroyRegion(reg2);
|
||||
reg2 = reg3;
|
||||
// reg2 == screen j
|
||||
|
||||
reg3 = XCreateRegion();
|
||||
XSubtractRegion(reg, reg2, reg3);
|
||||
XDestroyRegion(reg);
|
||||
XDestroyRegion(reg2);
|
||||
reg = reg3;
|
||||
// reg now has had screen j cut out of the boundary
|
||||
}
|
||||
// reg is the result of starting with screen i and then with a
|
||||
// 1 pixel boundary around it havnig adjacent screens "cut out"
|
||||
// of that boundary leaving only extra bounds where no screens
|
||||
// are adjacent
|
||||
// create just a rect with the screen in it
|
||||
reg2 = XCreateRegion();
|
||||
reg3 = XCreateRegion();
|
||||
xrect.x = screens[i].x;
|
||||
xrect.y = screens[i].y;
|
||||
xrect.width = screens[i].width;
|
||||
xrect.height = screens[i].height;
|
||||
XUnionRectWithRegion(&xrect, reg3, reg2);
|
||||
XDestroyRegion(reg3);
|
||||
|
||||
// now subtract it
|
||||
reg3 = XCreateRegion();
|
||||
XSubtractRegion(reg, reg2, reg3);
|
||||
XDestroyRegion(reg);
|
||||
XDestroyRegion(reg2);
|
||||
reg = reg3;
|
||||
}
|
||||
if (reg)
|
||||
{
|
||||
// walk rects and create barriers
|
||||
for (j = 0; j < reg->numRects; j++)
|
||||
for (i = 0; i < reg->numRects; i++)
|
||||
{
|
||||
int x1, y1, x2, y2;
|
||||
|
||||
|
@ -592,14 +590,15 @@ ecore_x_root_screen_barriers_set(Ecore_X_Rectangle *screens, int num)
|
|||
if (!t)
|
||||
{
|
||||
bar_num--;
|
||||
XDestroyRegion(reg);
|
||||
return;
|
||||
}
|
||||
bar = t;
|
||||
}
|
||||
x1 = reg->rects[j].x1;
|
||||
y1 = reg->rects[j].y1;
|
||||
x2 = reg->rects[j].x2 - 1;
|
||||
y2 = reg->rects[j].y2 - 1;
|
||||
x1 = reg->rects[i].x1;
|
||||
y1 = reg->rects[i].y1;
|
||||
x2 = reg->rects[i].x2 - 1;
|
||||
y2 = reg->rects[i].y2 - 1;
|
||||
bar[bar_num - 1] =
|
||||
XFixesCreatePointerBarrier(_ecore_x_disp,
|
||||
DefaultRootWindow(_ecore_x_disp),
|
||||
|
|
|
@ -13,6 +13,10 @@
|
|||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
#ifdef _WIN32
|
||||
# include "evil_private.h" /* setenv */
|
||||
#endif
|
||||
|
||||
#include "Eo.h"
|
||||
#include "Eina.h"
|
||||
#include "Ecore.h"
|
||||
|
|
|
@ -545,91 +545,6 @@ efreet_desktop_util_cache_file(void)
|
|||
/*
|
||||
* Needs EAPI because of helper binaries
|
||||
*/
|
||||
#define SHSH(n, v) ((((v) << (n)) & 0xffffffff) | ((v) >> (32 - (n))))
|
||||
|
||||
static inline int
|
||||
int_to_bigendian(int in)
|
||||
{
|
||||
static const unsigned char test[4] = { 0x11, 0x22, 0x33, 0x44 };
|
||||
static const unsigned int *test_i = (const unsigned int *)test;
|
||||
if (test_i[0] == 0x44332211) return eina_swap32(in);
|
||||
return in;
|
||||
}
|
||||
|
||||
static void
|
||||
sha1(unsigned char *data, int size, unsigned char *dst)
|
||||
{
|
||||
unsigned int digest[5], word[80], wa, wb, wc, wd, we, t;
|
||||
unsigned char buf[64], *d;
|
||||
int idx, left, i;
|
||||
const unsigned int magic[4] =
|
||||
{ 0x5a827999, 0x6ed9eba1, 0x8f1bbcdc, 0xca62c1d6 };
|
||||
|
||||
idx = 0;
|
||||
digest[0] = 0x67452301; digest[1] = 0xefcdab89; digest[2] = 0x98badcfe;
|
||||
digest[3] = 0x10325476; digest[4] = 0xc3d2e1f0;
|
||||
|
||||
memset(buf, 0, sizeof(buf));
|
||||
for (left = size, d = data; left > 0; left--, d++)
|
||||
{
|
||||
if ((idx == 0) && (left < 64))
|
||||
{
|
||||
memset(buf, 0, 60);
|
||||
buf[60] = (size >> 24) & 0xff;
|
||||
buf[61] = (size >> 16) & 0xff;
|
||||
buf[62] = (size >> 8) & 0xff;
|
||||
buf[63] = (size) & 0xff;
|
||||
}
|
||||
buf[idx] = *d;
|
||||
idx++;
|
||||
if ((idx == 64) || (left == 1))
|
||||
{
|
||||
if ((left == 1) && (idx < 64)) buf[idx] = 0x80;
|
||||
for (i = 0; i < 16; i++)
|
||||
{
|
||||
word[i] = (unsigned int)buf[(i * 4) ] << 24;
|
||||
word[i] |= (unsigned int)buf[(i * 4) + 1] << 16;
|
||||
word[i] |= (unsigned int)buf[(i * 4) + 2] << 8;
|
||||
word[i] |= (unsigned int)buf[(i * 4) + 3];
|
||||
}
|
||||
for (i = 16; i < 80; i++)
|
||||
word[i] = SHSH(1,
|
||||
word[i - 3 ] ^ word[i - 8 ] ^
|
||||
word[i - 14] ^ word[i - 16]);
|
||||
wa = digest[0]; wb = digest[1]; wc = digest[2];
|
||||
wd = digest[3]; we = digest[4];
|
||||
for (i = 0; i < 80; i++)
|
||||
{
|
||||
if (i < 20)
|
||||
t = SHSH(5, wa) + ((wb & wc) | ((~wb) & wd)) +
|
||||
we + word[i] + magic[0];
|
||||
else if (i < 40)
|
||||
t = SHSH(5, wa) + (wb ^ wc ^ wd) +
|
||||
we + word[i] + magic[1];
|
||||
else if (i < 60)
|
||||
t = SHSH(5, wa) + ((wb & wc) | (wb & wd) | (wc & wd)) +
|
||||
we + word[i] + magic[2];
|
||||
else if (i < 80)
|
||||
t = SHSH(5, wa) + (wb ^ wc ^ wd) +
|
||||
we + word[i] + magic[3];
|
||||
we = wd;
|
||||
wd = wc;
|
||||
wc = SHSH(30, wb);
|
||||
wb = wa;
|
||||
wa = t;
|
||||
}
|
||||
digest[0] += wa; digest[1] += wb; digest[2] += wc;
|
||||
digest[3] += wd; digest[4] += we;
|
||||
idx = 0;
|
||||
}
|
||||
}
|
||||
t = int_to_bigendian(digest[0]); digest[0] = t;
|
||||
t = int_to_bigendian(digest[1]); digest[1] = t;
|
||||
t = int_to_bigendian(digest[2]); digest[2] = t;
|
||||
t = int_to_bigendian(digest[3]); digest[3] = t;
|
||||
t = int_to_bigendian(digest[4]); digest[4] = t;
|
||||
memcpy(dst, digest, 5 * 4);
|
||||
}
|
||||
|
||||
EAPI Eina_Bool
|
||||
efreet_file_cache_fill(const char *file, Efreet_Cache_Check *check)
|
||||
|
@ -651,7 +566,7 @@ efreet_file_cache_fill(const char *file, Efreet_Cache_Check *check)
|
|||
if ((size > 0) && ((size_t)size >= sizeof(link))) return EINA_FALSE;
|
||||
if (stat(file, &st) != 0) return EINA_FALSE;
|
||||
}
|
||||
if (size > 0) sha1((unsigned char *)link, size, check->link_sha1);
|
||||
if (size > 0) eina_sha1((const unsigned char *)link, size, check->link_sha1);
|
||||
#endif
|
||||
check->uid = st.st_uid;
|
||||
check->gid = st.st_gid;
|
||||
|
|
|
@ -277,6 +277,7 @@ extern "C" {
|
|||
#include <eina_promise.h>
|
||||
#include <eina_vpath.h>
|
||||
#include <eina_abstract_content.h>
|
||||
#include <eina_sha.h>
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
|
|
@ -293,12 +293,14 @@ _signal_shutdown(void)
|
|||
}
|
||||
|
||||
static void
|
||||
_collect_bt(pthread_t pth)
|
||||
_collect_bt(Eina_Thread th)
|
||||
{
|
||||
// this async signals the thread to switch to the deebug signal handler
|
||||
// and collect a backtrace and other info from inside the thread
|
||||
#ifndef _WIN32
|
||||
pthread_kill(pth, SIG);
|
||||
pthread_kill((pthread_t)th, SIG); // we can cast Eina_Thread -> pthread_t
|
||||
#else
|
||||
(th); // silenmce unused warn
|
||||
#endif
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,122 @@
|
|||
/* EINA - EFL data type library
|
||||
* Copyright (C) 2023 Carsten Haitzler
|
||||
*
|
||||
* 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, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
# include "config.h"
|
||||
#endif
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#include "eina_private.h"
|
||||
#include "eina_sha.h"
|
||||
#include "eina_cpu.h"
|
||||
|
||||
/*============================================================================*
|
||||
* API *
|
||||
*============================================================================*/
|
||||
|
||||
|
||||
EINA_API void
|
||||
eina_sha1(const unsigned char *data, int size, unsigned char dst[20])
|
||||
{
|
||||
#define SHSH(n, v) ((((v) << (n)) & 0xffffffff) | ((v) >> (32 - (n))))
|
||||
unsigned int digest[5], word[80], wa, wb, wc, wd, we, t;
|
||||
unsigned char buf[64];
|
||||
const unsigned char *d;
|
||||
int idx, left, i;
|
||||
const unsigned int magic[4] =
|
||||
{
|
||||
0x5a827999,
|
||||
0x6ed9eba1,
|
||||
0x8f1bbcdc,
|
||||
0xca62c1d6
|
||||
};
|
||||
|
||||
idx = 0;
|
||||
digest[0] = 0x67452301;
|
||||
digest[1] = 0xefcdab89;
|
||||
digest[2] = 0x98badcfe;
|
||||
digest[3] = 0x10325476;
|
||||
digest[4] = 0xc3d2e1f0;
|
||||
|
||||
memset(buf, 0, sizeof(buf));
|
||||
for (left = size, d = data; left > 0; left--, d++)
|
||||
{
|
||||
if ((idx == 0) && (left < 64))
|
||||
{
|
||||
memset(buf, 0, 60);
|
||||
buf[60] = (size >> 24) & 0xff;
|
||||
buf[61] = (size >> 16) & 0xff;
|
||||
buf[62] = (size >> 8) & 0xff;
|
||||
buf[63] = (size) & 0xff;
|
||||
}
|
||||
buf[idx] = *d;
|
||||
idx++;
|
||||
if ((idx == 64) || (left == 1))
|
||||
{
|
||||
if ((left == 1) && (idx < 64)) buf[idx] = 0x80;
|
||||
for (i = 0; i < 16; i++)
|
||||
{
|
||||
word[i] = (unsigned int)buf[(i * 4) ] << 24;
|
||||
word[i] |= (unsigned int)buf[(i * 4) + 1] << 16;
|
||||
word[i] |= (unsigned int)buf[(i * 4) + 2] << 8;
|
||||
word[i] |= (unsigned int)buf[(i * 4) + 3];
|
||||
}
|
||||
for (i = 16; i < 80; i++)
|
||||
word[i] = SHSH(1,
|
||||
word[i - 3 ] ^ word[i - 8 ] ^
|
||||
word[i - 14] ^ word[i - 16]);
|
||||
wa = digest[0];
|
||||
wb = digest[1];
|
||||
wc = digest[2];
|
||||
wd = digest[3];
|
||||
we = digest[4];
|
||||
for (i = 0; i < 80; i++)
|
||||
{
|
||||
if (i < 20)
|
||||
t = SHSH(5, wa) + ((wb & wc) | ((~wb) & wd)) + we + word[i] + magic[0];
|
||||
else if (i < 40)
|
||||
t = SHSH(5, wa) + (wb ^ wc ^ wd) + we + word[i] + magic[1];
|
||||
else if (i < 60)
|
||||
t = SHSH(5, wa) + ((wb & wc) | (wb & wd) | (wc & wd)) + we + word[i] + magic[2];
|
||||
else if (i < 80)
|
||||
t = SHSH(5, wa) + (wb ^ wc ^ wd) + we + word[i] + magic[3];
|
||||
we = wd;
|
||||
wd = wc;
|
||||
wc = SHSH(30, wb);
|
||||
wb = wa;
|
||||
wa = t;
|
||||
}
|
||||
digest[0] += wa;
|
||||
digest[1] += wb;
|
||||
digest[2] += wc;
|
||||
digest[3] += wd;
|
||||
digest[4] += we;
|
||||
idx = 0;
|
||||
}
|
||||
}
|
||||
|
||||
t = eina_htonl(digest[0]); digest[0] = t;
|
||||
t = eina_htonl(digest[1]); digest[1] = t;
|
||||
t = eina_htonl(digest[2]); digest[2] = t;
|
||||
t = eina_htonl(digest[3]); digest[3] = t;
|
||||
t = eina_htonl(digest[4]); digest[4] = t;
|
||||
|
||||
memcpy(dst, digest, 5 * 4);
|
||||
}
|
|
@ -0,0 +1,38 @@
|
|||
/* EINA - EFL data type library
|
||||
* Copyright (C) 2023 Carsten Haitzler
|
||||
*
|
||||
* 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, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef EINA_SHA_H_
|
||||
#define EINA_SHA_H_
|
||||
|
||||
/**
|
||||
* @brief Calculate a SHA1 checksum of data
|
||||
*
|
||||
* This function calculates a SHA1 checksum of the binary data pointed to by
|
||||
* @p data of size @p size in bytes and will fill 20 bytes pointed to by
|
||||
* @p dst with the resulting 20 byte binary SHA1 sum.
|
||||
*
|
||||
* The input data should be a valid pointer to at least @p size bytes of data
|
||||
* that will be summed. @p dst should also point to a buffer of at least 20
|
||||
* bytes in size to store the checksum.
|
||||
*
|
||||
* @since 1.27
|
||||
*/
|
||||
EINA_API void eina_sha1(const unsigned char *data, int size, unsigned char dst[20]) EINA_ARG_NONNULL(1);
|
||||
|
||||
|
||||
#endif
|
|
@ -113,7 +113,8 @@ public_sub_headers = [
|
|||
'eina_freeq.h',
|
||||
'eina_slstr.h',
|
||||
'eina_vpath.h',
|
||||
'eina_abstract_content.h'
|
||||
'eina_abstract_content.h',
|
||||
'eina_sha.h'
|
||||
]
|
||||
|
||||
public_headers = [
|
||||
|
@ -197,6 +198,7 @@ eina_src = files([
|
|||
'eina_vpath.c',
|
||||
'eina_vpath_xdg.c',
|
||||
'eina_abstract_content.c',
|
||||
'eina_sha.c',
|
||||
]) + eina_mp_sources
|
||||
|
||||
if sys_windows == true
|
||||
|
|
|
@ -1526,7 +1526,7 @@ _efl_ui_focus_manager_calc_efl_ui_focus_manager_manager_focus_set(Eo *obj, Efl_U
|
|||
}
|
||||
else
|
||||
{
|
||||
ERR("Could not fetch a node located at %p", node->focusable);
|
||||
F_DBG("Could not fetch a node located at %p", node->focusable);
|
||||
goto end;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -329,7 +329,7 @@ _drag_start(void *data,
|
|||
elm_object_focus_set(data, EINA_TRUE);
|
||||
_slider_update(data, EINA_TRUE);
|
||||
efl_event_callback_call(data, EFL_UI_SLIDER_INTERVAL_EVENT_SLIDER_DRAG_START, NULL);
|
||||
elm_widget_scroll_freeze_push(data);
|
||||
efl_ui_widget_scroll_freeze_push(data);
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -340,7 +340,7 @@ _drag_stop(void *data,
|
|||
{
|
||||
_slider_update(data, EINA_TRUE);
|
||||
efl_event_callback_call(data, EFL_UI_SLIDER_INTERVAL_EVENT_SLIDER_DRAG_STOP, NULL);
|
||||
elm_widget_scroll_freeze_pop(data);
|
||||
efl_ui_widget_scroll_freeze_pop(data);
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -413,7 +413,7 @@ _spacer_move_cb(void *data,
|
|||
{
|
||||
if (!sd->frozen)
|
||||
{
|
||||
elm_widget_scroll_freeze_push(data);
|
||||
efl_ui_widget_scroll_freeze_push(data);
|
||||
sd->frozen = EINA_TRUE;
|
||||
}
|
||||
ev->event_flags &= ~EVAS_EVENT_FLAG_ON_HOLD;
|
||||
|
@ -427,7 +427,7 @@ _spacer_move_cb(void *data,
|
|||
(data, EFL_UI_SLIDER_INTERVAL_EVENT_SLIDER_DRAG_STOP, NULL);
|
||||
if (sd->frozen)
|
||||
{
|
||||
elm_widget_scroll_freeze_pop(data);
|
||||
efl_ui_widget_scroll_freeze_pop(data);
|
||||
sd->frozen = EINA_FALSE;
|
||||
}
|
||||
return;
|
||||
|
@ -466,7 +466,7 @@ _spacer_up_cb(void *data,
|
|||
|
||||
if (sd->frozen)
|
||||
{
|
||||
elm_widget_scroll_freeze_pop(data);
|
||||
efl_ui_widget_scroll_freeze_pop(data);
|
||||
sd->frozen = EINA_FALSE;
|
||||
}
|
||||
}
|
||||
|
@ -492,7 +492,7 @@ _mouse_out_cb(void *data EINA_UNUSED,
|
|||
static char *
|
||||
_access_info_cb(void *data EINA_UNUSED, Evas_Object *obj)
|
||||
{
|
||||
const char *txt = elm_widget_access_info_get(obj);
|
||||
const char *txt = efl_ui_widget_access_info_get(obj);
|
||||
|
||||
if (!txt) txt = elm_layout_text_get(obj, NULL);
|
||||
if (txt) return strdup(txt);
|
||||
|
@ -506,7 +506,7 @@ _access_state_cb(void *data EINA_UNUSED, Evas_Object *obj)
|
|||
char *ret;
|
||||
Eina_Strbuf *buf = eina_strbuf_new();
|
||||
|
||||
if (elm_widget_disabled_get(obj))
|
||||
if (efl_ui_widget_disabled_get(obj))
|
||||
eina_strbuf_append(buf, " state: disabled");
|
||||
|
||||
if (eina_strbuf_length_get(buf))
|
||||
|
@ -713,7 +713,7 @@ _key_action_drag(Evas_Object *obj, const char *params)
|
|||
EOLIAN static Eina_Bool
|
||||
_efl_ui_slider_interval_efl_ui_widget_on_access_activate(Eo *obj, Efl_Ui_Slider_Interval_Data *sd, Efl_Ui_Activate act)
|
||||
{
|
||||
if (elm_widget_disabled_get(obj)) return EINA_FALSE;
|
||||
if (efl_ui_widget_disabled_get) return EINA_FALSE;
|
||||
if (act == EFL_UI_ACTIVATE_DEFAULT) return EINA_FALSE;
|
||||
|
||||
if ((act == EFL_UI_ACTIVATE_UP) ||
|
||||
|
|
|
@ -3556,9 +3556,6 @@ _entry_selection_callbacks_unregister(Evas_Object *obj)
|
|||
edje_object_signal_callback_del_full
|
||||
(sd->entry_edje, "selection,cleared", "elm.text",
|
||||
_entry_selection_cleared_signal_cb, obj);
|
||||
edje_object_signal_callback_del_full
|
||||
(sd->entry_edje, "entry,paste,request,*", "elm.text",
|
||||
_entry_paste_request_signal_cb, obj);
|
||||
edje_object_signal_callback_del_full
|
||||
(sd->entry_edje, "entry,copy,notify", "elm.text",
|
||||
_entry_copy_notify_signal_cb, obj);
|
||||
|
@ -3587,9 +3584,6 @@ _entry_selection_callbacks_register(Evas_Object *obj)
|
|||
edje_object_signal_callback_add
|
||||
(sd->entry_edje, "selection,cleared", "elm.text",
|
||||
_entry_selection_cleared_signal_cb, obj);
|
||||
edje_object_signal_callback_add
|
||||
(sd->entry_edje, "entry,paste,request,*", "elm.text",
|
||||
_entry_paste_request_signal_cb, obj);
|
||||
edje_object_signal_callback_add
|
||||
(sd->entry_edje, "entry,copy,notify", "elm.text",
|
||||
_entry_copy_notify_signal_cb, obj);
|
||||
|
@ -3920,6 +3914,10 @@ _elm_entry_efl_canvas_group_group_add(Eo *obj, Elm_Entry_Data *priv)
|
|||
(priv->entry_edje, "preedit,changed", "elm.text",
|
||||
_entry_preedit_changed_signal_cb, obj);
|
||||
|
||||
edje_object_signal_callback_add
|
||||
(priv->entry_edje, "entry,paste,request,*", "elm.text",
|
||||
_entry_paste_request_signal_cb, obj);
|
||||
|
||||
_entry_selection_callbacks_register(obj);
|
||||
|
||||
edje_object_signal_callback_add
|
||||
|
|
|
@ -423,27 +423,37 @@ _internal_elm_icon_standard_set(Evas_Object *obj,
|
|||
Eina_Bool *fdo)
|
||||
{
|
||||
char *tmp;
|
||||
const char *stdtmp;
|
||||
Eina_Bool ret = EINA_FALSE;
|
||||
|
||||
ELM_ICON_DATA_GET(obj, sd);
|
||||
|
||||
/* try locating the icon using the specified theme */
|
||||
if (!strcmp(ELM_CONFIG_ICON_THEME_ELEMENTARY, elm_config_icon_theme_get()))
|
||||
stdtmp = sd->stdicon;
|
||||
sd->stdicon = NULL;
|
||||
ret = _icon_standard_set(obj, name);
|
||||
sd->stdicon = stdtmp;
|
||||
if (ret && fdo) *fdo = EINA_FALSE;
|
||||
if (!ret)
|
||||
{
|
||||
ret = _icon_standard_set(obj, name);
|
||||
if (ret && fdo) *fdo = EINA_FALSE;
|
||||
|
||||
if (!ret)
|
||||
/* try locating the icon using the specified theme */
|
||||
if (!strcmp(ELM_CONFIG_ICON_THEME_ELEMENTARY, elm_config_icon_theme_get()))
|
||||
{
|
||||
ret = _icon_freedesktop_set(obj, "hicolor", name, _icon_size_min_get(obj));
|
||||
ret = _icon_standard_set(obj, name);
|
||||
if (ret && fdo) *fdo = EINA_FALSE;
|
||||
|
||||
if (!ret)
|
||||
{
|
||||
ret = _icon_freedesktop_set(obj, "hicolor", name, _icon_size_min_get(obj));
|
||||
if (ret && fdo) *fdo = EINA_TRUE;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
ret = _icon_freedesktop_set(obj, NULL, name, _icon_size_min_get(obj));
|
||||
if (ret && fdo) *fdo = EINA_TRUE;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
ret = _icon_freedesktop_set(obj, NULL, name, _icon_size_min_get(obj));
|
||||
if (ret && fdo) *fdo = EINA_TRUE;
|
||||
}
|
||||
|
||||
if (ret)
|
||||
{
|
||||
|
|
|
@ -702,6 +702,7 @@ elementary_pub_headers = [
|
|||
'elm_view_form_eo.h',
|
||||
'elm_view_list_eo.h',
|
||||
'elm_web_eo.legacy.h',
|
||||
'elm_widget_item_container_eo.h',
|
||||
'elm_widget_item_container_eo.legacy.h',
|
||||
'elm_widget_item_eo.legacy.h',
|
||||
'elm_widget_item_static_focus_eo.legacy.h',
|
||||
|
|
|
@ -0,0 +1,4 @@
|
|||
Look at implementing support for libei for emulated input support
|
||||
(Simotek request)
|
||||
|
||||
https://gitlab.freedesktop.org/libinput/libei
|
|
@ -94,7 +94,7 @@ emile_base64_encode_common(const Eina_Binbuf *in, Eina_Bool is_base64url_encode)
|
|||
|
||||
dest[k] = '\0';
|
||||
|
||||
return eina_strbuf_manage_new(dest);
|
||||
return eina_strbuf_manage_new_length(dest, k);
|
||||
}
|
||||
|
||||
static Eina_Binbuf *
|
||||
|
|
|
@ -1929,15 +1929,15 @@ evas_font_object_rehint(Evas_Object *eo_obj)
|
|||
Evas_Object_Protected_Data *obj = efl_data_scope_get(eo_obj, EFL_CANVAS_OBJECT_CLASS);
|
||||
if (obj->is_smart)
|
||||
{
|
||||
EINA_INLIST_FOREACH(evas_object_smart_members_get_direct(eo_obj), obj)
|
||||
evas_font_object_rehint(obj->object);
|
||||
EINA_INLIST_FOREACH(evas_object_smart_members_get_direct(eo_obj), obj)
|
||||
evas_font_object_rehint(obj->object);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!strcmp(obj->type, "text"))
|
||||
_evas_object_text_rehint(eo_obj);
|
||||
if (!strcmp(obj->type, "textblock"))
|
||||
_evas_object_textblock_rehint(eo_obj);
|
||||
if (!strcmp(obj->type, "text"))
|
||||
_evas_object_text_rehint(eo_obj);
|
||||
if (!strcmp(obj->type, "textblock"))
|
||||
_evas_object_textblock_rehint(eo_obj);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1953,10 +1953,10 @@ evas_font_hinting_set(Eo *eo_e, Evas_Font_Hinting_Flags hinting)
|
|||
|
||||
EINA_INLIST_FOREACH(e->layers, lay)
|
||||
{
|
||||
Evas_Object_Protected_Data *obj;
|
||||
Evas_Object_Protected_Data *obj;
|
||||
|
||||
EINA_INLIST_FOREACH(lay->objects, obj)
|
||||
evas_font_object_rehint(obj->object);
|
||||
EINA_INLIST_FOREACH(lay->objects, obj)
|
||||
evas_font_object_rehint(obj->object);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -25,6 +25,8 @@ EVAS_API Cutout_Rects *evas_common_draw_context_cutouts_new (vo
|
|||
EVAS_API void evas_common_draw_context_cutouts_free (Cutout_Rects* rects);
|
||||
EVAS_API void evas_common_draw_context_cutouts_real_free (Cutout_Rects* rects);
|
||||
EVAS_API void evas_common_draw_context_cutouts_del (Cutout_Rects* rects, int idx);
|
||||
EVAS_API void evas_common_draw_context_cutout_max_set (RGBA_Draw_Context *dc, int max);
|
||||
EVAS_API void evas_common_draw_context_cutout_size_min_set (RGBA_Draw_Context *dc, int min);
|
||||
EVAS_API void evas_common_draw_context_add_cutout (RGBA_Draw_Context *dc, int x, int y, int w, int h);
|
||||
EVAS_API void evas_common_draw_context_clear_cutouts (RGBA_Draw_Context *dc);
|
||||
EVAS_API Cutout_Rects *evas_common_draw_context_apply_cutouts (RGBA_Draw_Context *dc, Cutout_Rects *recycle);
|
||||
|
|
|
@ -174,6 +174,8 @@ evas_common_draw_context_new(void)
|
|||
dc = _evas_common_draw_context_find();
|
||||
if (!dc) return NULL;
|
||||
memset(dc, 0, sizeof(RGBA_Draw_Context));
|
||||
dc->cutout.count_max = 0x7fffffff;
|
||||
dc->cutout.size_min = 8 * 8;
|
||||
return dc;
|
||||
}
|
||||
|
||||
|
@ -296,11 +298,23 @@ evas_common_draw_context_unset_multiplier(RGBA_Draw_Context *dc)
|
|||
dc->mul.use = 0;
|
||||
}
|
||||
|
||||
EVAS_API void
|
||||
evas_common_draw_context_cutout_max_set(RGBA_Draw_Context *dc, int max)
|
||||
{
|
||||
dc->cutout.count_max = max;
|
||||
}
|
||||
|
||||
EVAS_API void
|
||||
evas_common_draw_context_cutout_size_min_set(RGBA_Draw_Context *dc, int min)
|
||||
{
|
||||
dc->cutout.size_min = min;
|
||||
}
|
||||
|
||||
EVAS_API void
|
||||
evas_common_draw_context_add_cutout(RGBA_Draw_Context *dc, int x, int y, int w, int h)
|
||||
{
|
||||
// if (dc->cutout.rects > 512) return;
|
||||
if (dc->cutout.active >= dc->cutout.count_max) return;
|
||||
if ((w * h) < dc->cutout.size_min) return;
|
||||
if (dc->clip.use)
|
||||
{
|
||||
#if 1 // this is a bit faster
|
||||
|
@ -335,8 +349,8 @@ evas_common_draw_context_add_cutout(RGBA_Draw_Context *dc, int x, int y, int w,
|
|||
RECTS_CLIP_TO_RECT(x, y, w, h,
|
||||
dc->clip.x, dc->clip.y, dc->clip.w, dc->clip.h);
|
||||
#endif
|
||||
if ((w * h) < dc->cutout.size_min) return;
|
||||
}
|
||||
if ((w * h) <= (8 * 8)) return;
|
||||
if (dc->cutout.last_add.w > 0)
|
||||
{
|
||||
if ((dc->cutout.last_add.x == x) && (dc->cutout.last_add.y == y) &&
|
||||
|
|
|
@ -68,6 +68,8 @@ static const struct ext_loader_s loaders[] =
|
|||
|
||||
MATCHING(".jxl", "jxl"),
|
||||
|
||||
MATCHING(".qoi", "qoi"),
|
||||
|
||||
MATCHING(".avif", "avif"),
|
||||
MATCHING(".avifs", "avif"),
|
||||
|
||||
|
@ -195,8 +197,8 @@ static const struct ext_loader_s loaders[] =
|
|||
static const char *loaders_name[] =
|
||||
{ /* in order of most likely needed */
|
||||
"png", "jpeg", "eet", "xpm", "tiff", "gif", "svg", "webp", "pmaps",
|
||||
"bmp", "tga", "wbmp", "ico", "psd", "jp2k", "dds", "jxl", "avif", "heif",
|
||||
"generic"
|
||||
"bmp", "tga", "wbmp", "ico", "psd", "jp2k", "dds", "jxl", "qoi", "avif",
|
||||
"heif", "generic"
|
||||
};
|
||||
|
||||
struct evas_image_foreach_loader_data
|
||||
|
|
|
@ -37,6 +37,8 @@ evas_common_save_image_to_file(RGBA_Image *im, const char *file, const char *key
|
|||
saver = "avif";
|
||||
if (!strcasecmp(p, "jxl"))
|
||||
saver = "jxl";
|
||||
if (!strcasecmp(p, "qoi"))
|
||||
saver = "qoi";
|
||||
}
|
||||
|
||||
if (saver)
|
||||
|
|
|
@ -210,6 +210,7 @@ EVAS_EINA_STATIC_MODULE_DEFINE(image_loader, jxl);
|
|||
EVAS_EINA_STATIC_MODULE_DEFINE(image_loader, pmaps);
|
||||
EVAS_EINA_STATIC_MODULE_DEFINE(image_loader, png);
|
||||
EVAS_EINA_STATIC_MODULE_DEFINE(image_loader, psd);
|
||||
EVAS_EINA_STATIC_MODULE_DEFINE(image_loader, qoi);
|
||||
EVAS_EINA_STATIC_MODULE_DEFINE(image_loader, svg);
|
||||
EVAS_EINA_STATIC_MODULE_DEFINE(image_loader, tga);
|
||||
EVAS_EINA_STATIC_MODULE_DEFINE(image_loader, tiff);
|
||||
|
@ -230,6 +231,7 @@ EVAS_EINA_STATIC_MODULE_DEFINE(image_saver, eet);
|
|||
EVAS_EINA_STATIC_MODULE_DEFINE(image_saver, jpeg);
|
||||
EVAS_EINA_STATIC_MODULE_DEFINE(image_saver, jxl);
|
||||
EVAS_EINA_STATIC_MODULE_DEFINE(image_saver, png);
|
||||
EVAS_EINA_STATIC_MODULE_DEFINE(image_saver, qoi);
|
||||
EVAS_EINA_STATIC_MODULE_DEFINE(image_saver, tiff);
|
||||
EVAS_EINA_STATIC_MODULE_DEFINE(image_saver, webp);
|
||||
EVAS_EINA_STATIC_MODULE_DEFINE(image_saver, tgv);
|
||||
|
@ -334,6 +336,9 @@ static const struct {
|
|||
#ifdef EVAS_STATIC_BUILD_PSD
|
||||
EVAS_EINA_STATIC_MODULE_USE(image_loader, psd),
|
||||
#endif
|
||||
#ifdef EVAS_STATIC_BUILD_QOI
|
||||
EVAS_EINA_STATIC_MODULE_USE(image_loader, qoi),
|
||||
#endif
|
||||
#ifdef EVAS_STATIC_BUILD_SVG
|
||||
EVAS_EINA_STATIC_MODULE_USE(image_loader, svg),
|
||||
#endif
|
||||
|
@ -380,6 +385,9 @@ static const struct {
|
|||
#ifdef EVAS_STATIC_BUILD_PNG
|
||||
EVAS_EINA_STATIC_MODULE_USE(image_saver, png),
|
||||
#endif
|
||||
#ifdef EVAS_STATIC_BUILD_QOI
|
||||
EVAS_EINA_STATIC_MODULE_USE(image_saver, qoi),
|
||||
#endif
|
||||
#ifdef EVAS_STATIC_BUILD_TIFF
|
||||
EVAS_EINA_STATIC_MODULE_USE(image_saver, tiff),
|
||||
#endif
|
||||
|
|
|
@ -645,6 +645,8 @@ struct _Cutout_Rects
|
|||
Cutout_Rect *rects;
|
||||
int active;
|
||||
int max;
|
||||
int count_max;
|
||||
int size_min;
|
||||
struct {
|
||||
int x, w, y, h;
|
||||
} last_add;
|
||||
|
|
|
@ -21,7 +21,7 @@ evas_image_loaders_file = [
|
|||
['eet', 'static', [eet]],
|
||||
['generic', 'shared', [rt]],
|
||||
['gif', 'shared', [giflib]],
|
||||
['heif', 'shared', [heif]],
|
||||
['heif', 'shared', []],
|
||||
['ico', 'shared', []],
|
||||
['jpeg', 'static', [jpeg]],
|
||||
['jp2k', 'shared', [libopenjp2]],
|
||||
|
@ -29,6 +29,7 @@ evas_image_loaders_file = [
|
|||
['pmaps', 'shared', []],
|
||||
['png', 'static', [png]],
|
||||
['psd', 'shared', []],
|
||||
['qoi', 'shared', []],
|
||||
['tga', 'shared', []],
|
||||
['tgv', 'shared', [rg_etc, lz4]],
|
||||
['tiff', 'shared', [tiff]],
|
||||
|
@ -43,6 +44,7 @@ evas_image_savers_file = [
|
|||
['jpeg', 'static', [jpeg]],
|
||||
['jxl' , 'shared', [libjxl, libjxl_threads]],
|
||||
['png', 'static', [png]],
|
||||
['qoi', 'shared', []],
|
||||
['tgv', 'shared', [rg_etc, lz4]],
|
||||
['tiff', 'shared', [tiff]],
|
||||
['webp', 'shared', [webp]],
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
engines = [
|
||||
['cocoa', ['cocoa']],
|
||||
['drm', ['drm']],
|
||||
# ['drm', ['drm']],
|
||||
['fb', ['fb']],
|
||||
['sdl', ['sdl']],
|
||||
['wayland', ['wl']],
|
||||
|
|
|
@ -158,7 +158,8 @@ struct _Evas_GL_Shared
|
|||
Eina_Bool etc1_subimage : 1;
|
||||
Eina_Bool s3tc : 1;
|
||||
// tuning params - per gpu/cpu combo?
|
||||
#define DEF_CUTOUT 4096
|
||||
#define DEF_CUTOUT 64
|
||||
#define DEF_CUTOUT_SIZE_MIN (64*64)
|
||||
|
||||
#define MAX_PIPES 32
|
||||
#define DEF_PIPES 8
|
||||
|
@ -188,6 +189,9 @@ struct _Evas_GL_Shared
|
|||
struct {
|
||||
int max;
|
||||
} cutout;
|
||||
struct {
|
||||
int min;
|
||||
} cutout_size;
|
||||
struct {
|
||||
int max;
|
||||
} pipes;
|
||||
|
|
|
@ -1004,6 +1004,7 @@ evas_gl_common_context_new(void)
|
|||
// magic numbers that are a result of imperical testing and getting
|
||||
// "best case" performance across a range of systems
|
||||
shared->info.tune.cutout.max = DEF_CUTOUT;
|
||||
shared->info.tune.cutout_size.min = DEF_CUTOUT_SIZE_MIN;
|
||||
shared->info.tune.pipes.max = DEF_PIPES;
|
||||
shared->info.tune.atlas.max_alloc_size = DEF_ATLAS_ALLOC;
|
||||
shared->info.tune.atlas.max_alloc_alpha_size = DEF_ATLAS_ALLOC_ALPHA;
|
||||
|
@ -1040,6 +1041,7 @@ evas_gl_common_context_new(void)
|
|||
} while (0)
|
||||
|
||||
GETENVOPT("EVAS_GL_CUTOUT_MAX", cutout.max, -1, 0x7fffffff);
|
||||
GETENVOPT("EVAS_GL_CUTOUT_SIZE_MIN", cutout_size.min, -1, 0x7fffffff);
|
||||
GETENVOPT("EVAS_GL_PIPES_MAX", pipes.max, 1, MAX_PIPES);
|
||||
GETENVOPT("EVAS_GL_ATLAS_ALLOC_SIZE", atlas.max_alloc_size, MIN_ATLAS_ALLOC, MAX_ATLAS_ALLOC);
|
||||
GETENVOPT("EVAS_GL_ATLAS_ALLOC_ALPHA_SIZE", atlas.max_alloc_alpha_size, MIN_ATLAS_ALLOC_ALPHA, MAX_ATLAS_ALLOC_ALPHA);
|
||||
|
@ -1109,6 +1111,7 @@ evas_gl_common_context_new(void)
|
|||
"\n"
|
||||
"EVAS_GL_GET_PROGRAM_BINARY: %i\n"
|
||||
"EVAS_GL_CUTOUT_MAX: %i\n"
|
||||
"EVAS_GL_CUTOUT_SIZE_MIN: %i\n"
|
||||
"EVAS_GL_PIPES_MAX: %i\n"
|
||||
"EVAS_GL_ATLAS_ALLOC_SIZE: %i\n"
|
||||
"EVAS_GL_ATLAS_ALLOC_ALPHA_SIZE: %i\n"
|
||||
|
@ -1128,6 +1131,7 @@ evas_gl_common_context_new(void)
|
|||
|
||||
(int)shared->info.bin_program,
|
||||
(int)shared->info.tune.cutout.max,
|
||||
(int)shared->info.tune.cutout_size.min,
|
||||
(int)shared->info.tune.pipes.max,
|
||||
(int)shared->info.tune.atlas.max_alloc_size,
|
||||
(int)shared->info.tune.atlas.max_alloc_alpha_size,
|
||||
|
|
|
@ -788,6 +788,10 @@ _rotate_image_data(Render_Engine_GL_Generic *re, Evas_GL_Image *im1)
|
|||
|
||||
// Create a new and temporary context
|
||||
dc = evas_common_draw_context_new();
|
||||
evas_common_draw_context_cutout_max_set
|
||||
(dc, gl_context->shared->info.tune.cutout.max);
|
||||
evas_common_draw_context_cutout_size_min_set
|
||||
(dc, gl_context->shared->info.tune.cutout_size.min);
|
||||
evas_common_draw_context_set_clip(dc, 0, 0, im2->w, im2->h);
|
||||
gl_context->dc = dc;
|
||||
|
||||
|
@ -2317,6 +2321,23 @@ eng_pixel_alpha_get(void *image, int x, int y, DATA8 *alpha, int src_region_x, i
|
|||
return EINA_TRUE;
|
||||
}
|
||||
|
||||
static void *
|
||||
eng_context_new(void *engine)
|
||||
{
|
||||
Render_Engine_GL_Generic *re = engine;
|
||||
Evas_Engine_GL_Context *gl_context;
|
||||
void *ctx;
|
||||
|
||||
gl_context = gl_generic_context_find(re, 1);
|
||||
|
||||
ctx = pfunc.context_new(&re->software);
|
||||
evas_common_draw_context_cutout_max_set
|
||||
(ctx, gl_context->shared->info.tune.cutout.max);
|
||||
evas_common_draw_context_cutout_size_min_set
|
||||
(ctx, gl_context->shared->info.tune.cutout_size.min);
|
||||
return ctx;
|
||||
}
|
||||
|
||||
static void
|
||||
eng_context_flush(void *engine)
|
||||
{
|
||||
|
@ -3110,6 +3131,7 @@ module_open(Evas_Module *em)
|
|||
ORD(engine_new);
|
||||
ORD(engine_free);
|
||||
|
||||
ORD(context_new);
|
||||
ORD(context_clip_image_set);
|
||||
ORD(context_clip_image_unset);
|
||||
ORD(context_clip_image_get);
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
engines = [
|
||||
['buffer', []],
|
||||
['fb', ['fb']],
|
||||
['drm', ['drm']],
|
||||
# ['drm', ['drm']],
|
||||
['software_x11', ['x11']],
|
||||
['wayland_shm', ['wl']],
|
||||
]
|
||||
|
@ -28,7 +28,7 @@ endif
|
|||
if get_option('opengl') == 'es-egl'
|
||||
engines += [
|
||||
['wayland_egl', ['wl']],
|
||||
['gl_drm', ['drm']]
|
||||
# ['gl_drm', ['drm']]
|
||||
]
|
||||
have_gl_engine = true
|
||||
endif
|
||||
|
|
|
@ -65,7 +65,6 @@ evas_image_load_file_head_avif_internal(Evas_Loader_Internal *loader,
|
|||
codec_name = avifCodecName(decoder->codecChoice, AVIF_CODEC_FLAG_CAN_DECODE);
|
||||
if (!codec_name)
|
||||
{
|
||||
ERR("AV1 codec not available");
|
||||
*error = EVAS_LOAD_ERROR_GENERIC;
|
||||
goto destroy_decoder;
|
||||
}
|
||||
|
@ -76,14 +75,12 @@ evas_image_load_file_head_avif_internal(Evas_Loader_Internal *loader,
|
|||
res = avifDecoderParse(decoder);
|
||||
if (res != AVIF_RESULT_OK)
|
||||
{
|
||||
ERR("avif file format invalid");
|
||||
*error = EVAS_LOAD_ERROR_GENERIC;
|
||||
goto destroy_decoder;
|
||||
}
|
||||
|
||||
if (decoder->imageCount < 1)
|
||||
{
|
||||
ERR("avif file format invalid");
|
||||
*error = EVAS_LOAD_ERROR_GENERIC;
|
||||
goto destroy_decoder;
|
||||
}
|
||||
|
@ -91,7 +88,6 @@ evas_image_load_file_head_avif_internal(Evas_Loader_Internal *loader,
|
|||
res = avifDecoderNextImage(decoder);
|
||||
if (res != AVIF_RESULT_OK)
|
||||
{
|
||||
ERR("avif file format invalid");
|
||||
*error = EVAS_LOAD_ERROR_GENERIC;
|
||||
goto destroy_decoder;
|
||||
}
|
||||
|
@ -162,7 +158,6 @@ evas_image_load_file_data_avif_internal(Evas_Loader_Internal *loader,
|
|||
AVIF_CODEC_FLAG_CAN_DECODE);
|
||||
if (!codec_name)
|
||||
{
|
||||
ERR("AV1 codec not available");
|
||||
*error = EVAS_LOAD_ERROR_GENERIC;
|
||||
goto on_error;
|
||||
}
|
||||
|
|
|
@ -13,9 +13,90 @@ struct _Evas_Loader_Internal
|
|||
Eina_File *f;
|
||||
Evas_Image_Load_Opts *opts;
|
||||
struct heif_context* ctx;
|
||||
struct heif_image_handle *handle;
|
||||
};
|
||||
|
||||
static int _evas_loader_heif_log_dom = -1;
|
||||
static Eina_Module *_evas_loader_heif_mod = NULL;
|
||||
|
||||
#define LOAD(x) \
|
||||
if (!_evas_loader_heif_mod) { \
|
||||
if ((_evas_loader_heif_mod = eina_module_new(x))) { \
|
||||
if (!eina_module_load(_evas_loader_heif_mod)) { \
|
||||
eina_module_free(_evas_loader_heif_mod); \
|
||||
_evas_loader_heif_mod = NULL; \
|
||||
} \
|
||||
} \
|
||||
}
|
||||
|
||||
#define SYM(x) \
|
||||
if (!(x ## _f = eina_module_symbol_get(_evas_loader_heif_mod, #x))) { \
|
||||
ERR("Cannot find symbol '%s' in '%s'", \
|
||||
#x, eina_module_file_get(_evas_loader_heif_mod)); \
|
||||
goto error; \
|
||||
}
|
||||
|
||||
// heif_check_filetype
|
||||
typedef enum heif_filetype_result (*heif_check_filetype_t)(const uint8_t* data,
|
||||
int len);
|
||||
static heif_check_filetype_t heif_check_filetype_f = NULL;
|
||||
|
||||
// heif_context_alloc
|
||||
typedef struct heif_context* (*heif_context_alloc_t)(void);
|
||||
static heif_context_alloc_t heif_context_alloc_f = NULL;
|
||||
|
||||
// heif_context_free
|
||||
typedef void (*heif_context_free_t)(struct heif_context*);
|
||||
static heif_context_free_t heif_context_free_f = NULL;
|
||||
|
||||
// heif_context_get_primary_image_handle
|
||||
typedef struct heif_error (*heif_context_get_primary_image_handle_t)(struct heif_context* ctx,
|
||||
struct heif_image_handle**);
|
||||
static heif_context_get_primary_image_handle_t heif_context_get_primary_image_handle_f = NULL;
|
||||
|
||||
// heif_context_read_from_memory_without_copy
|
||||
typedef struct heif_error (*heif_context_read_from_memory_without_copy_t)(struct heif_context*,
|
||||
const void* mem, size_t size,
|
||||
const struct heif_reading_options*);
|
||||
static heif_context_read_from_memory_without_copy_t heif_context_read_from_memory_without_copy_f = NULL;
|
||||
|
||||
// heif_decode_image
|
||||
typedef struct heif_error (*heif_decode_image_t)(const struct heif_image_handle* in_handle,
|
||||
struct heif_image** out_img,
|
||||
enum heif_colorspace colorspace,
|
||||
enum heif_chroma chroma,
|
||||
const struct heif_decoding_options* options);
|
||||
static heif_decode_image_t heif_decode_image_f = NULL;
|
||||
|
||||
// heif_deinit
|
||||
typedef void (*heif_deinit_t)();
|
||||
static heif_deinit_t heif_deinit_f = NULL;
|
||||
|
||||
// heif_image_get_plane_readonly
|
||||
typedef const uint8_t* (*heif_image_get_plane_readonly_t)(const struct heif_image*,
|
||||
enum heif_channel channel,
|
||||
int* out_stride);
|
||||
static heif_image_get_plane_readonly_t heif_image_get_plane_readonly_f = NULL;
|
||||
|
||||
// heif_image_handle_get_height
|
||||
typedef int (*heif_image_handle_get_height_t)(const struct heif_image_handle* handle);
|
||||
static heif_image_handle_get_height_t heif_image_handle_get_height_f = NULL;
|
||||
|
||||
// heif_image_handle_get_width
|
||||
typedef int (*heif_image_handle_get_width_t)(const struct heif_image_handle* handle);
|
||||
static heif_image_handle_get_width_t heif_image_handle_get_width_f = NULL;
|
||||
|
||||
// heif_image_handle_has_alpha_channel
|
||||
typedef int (*heif_image_handle_has_alpha_channel_t)(const struct heif_image_handle*);
|
||||
static heif_image_handle_has_alpha_channel_t heif_image_handle_has_alpha_channel_f = NULL;
|
||||
|
||||
// heif_init
|
||||
typedef struct heif_error (*heif_init_t)(struct heif_init_params*);
|
||||
static heif_init_t heif_init_f = NULL;
|
||||
|
||||
// heif_image_handle_release
|
||||
typedef void (*heif_image_handle_release_t)(const struct heif_image_handle*);
|
||||
static heif_image_handle_release_t heif_image_handle_release_f = NULL;
|
||||
|
||||
#ifdef ERR
|
||||
# undef ERR
|
||||
|
@ -28,10 +109,10 @@ static int _evas_loader_heif_log_dom = -1;
|
|||
#define INF(...) EINA_LOG_DOM_INFO(_evas_loader_heif_log_dom, __VA_ARGS__)
|
||||
|
||||
static Eina_Bool
|
||||
evas_image_load_file_head_heif_internal(Evas_Loader_Internal *loader EINA_UNUSED,
|
||||
Emile_Image_Property *prop,
|
||||
void *map, size_t length,
|
||||
int *error)
|
||||
evas_image_load_file_head_heif_init(Evas_Loader_Internal *loader,
|
||||
Emile_Image_Property *prop,
|
||||
void *map, size_t length,
|
||||
int *error)
|
||||
{
|
||||
struct heif_context *ctx;
|
||||
struct heif_image_handle *handle;
|
||||
|
@ -45,14 +126,14 @@ evas_image_load_file_head_heif_internal(Evas_Loader_Internal *loader EINA_UNUSED
|
|||
|
||||
/* heif file must have a 12 bytes long header */
|
||||
if ((length < 12) ||
|
||||
(heif_check_filetype(map, length) == heif_filetype_no))
|
||||
(heif_check_filetype_f(map, length) != heif_filetype_yes_supported))
|
||||
{
|
||||
INF("HEIF header invalid");
|
||||
*error = EVAS_LOAD_ERROR_UNKNOWN_FORMAT;
|
||||
return ret;
|
||||
}
|
||||
|
||||
ctx = heif_context_alloc();
|
||||
ctx = heif_context_alloc_f();
|
||||
if (!ctx)
|
||||
{
|
||||
INF("cannot allocate heif_context");
|
||||
|
@ -60,24 +141,26 @@ evas_image_load_file_head_heif_internal(Evas_Loader_Internal *loader EINA_UNUSED
|
|||
return ret;
|
||||
}
|
||||
|
||||
err = heif_context_read_from_memory_without_copy(ctx, map, length, NULL);
|
||||
err = heif_context_read_from_memory_without_copy_f(ctx, map, length, NULL);
|
||||
if (err.code != heif_error_Ok)
|
||||
{
|
||||
INF("%s", err.message);
|
||||
*error = EVAS_LOAD_ERROR_UNKNOWN_FORMAT;
|
||||
goto free_ctx;
|
||||
heif_context_free_f(ctx);
|
||||
return ret;
|
||||
}
|
||||
|
||||
err = heif_context_get_primary_image_handle(ctx, &handle);
|
||||
err = heif_context_get_primary_image_handle_f(ctx, &handle);
|
||||
if (err.code != heif_error_Ok)
|
||||
{
|
||||
INF("%s", err.message);
|
||||
*error = EVAS_LOAD_ERROR_UNKNOWN_FORMAT;
|
||||
goto free_ctx;
|
||||
heif_context_free_f(ctx);
|
||||
return ret;
|
||||
}
|
||||
|
||||
prop->w = heif_image_handle_get_width(handle);
|
||||
prop->h = heif_image_handle_get_height(handle);
|
||||
prop->w = heif_image_handle_get_width_f(handle);
|
||||
prop->h = heif_image_handle_get_height_f(handle);
|
||||
|
||||
/* if size is invalid, we exit */
|
||||
if ((prop->w < 1) || (prop->h < 1) ||
|
||||
|
@ -88,22 +171,37 @@ evas_image_load_file_head_heif_internal(Evas_Loader_Internal *loader EINA_UNUSED
|
|||
*error = EVAS_LOAD_ERROR_RESOURCE_ALLOCATION_FAILED;
|
||||
else
|
||||
*error= EVAS_LOAD_ERROR_GENERIC;
|
||||
goto release_handle;
|
||||
heif_image_handle_release_f(handle);
|
||||
heif_context_free_f(ctx);
|
||||
return ret;
|
||||
}
|
||||
|
||||
prop->alpha = !!heif_image_handle_has_alpha_channel(handle);
|
||||
prop->alpha = !!heif_image_handle_has_alpha_channel_f(handle);
|
||||
loader->ctx = ctx;
|
||||
loader->handle = handle;
|
||||
|
||||
*error = EVAS_LOAD_ERROR_NONE;
|
||||
ret = EINA_TRUE;
|
||||
|
||||
release_handle:
|
||||
heif_image_handle_release(handle);
|
||||
free_ctx:
|
||||
heif_context_free(ctx);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static Eina_Bool
|
||||
evas_image_load_file_head_heif_internal(Evas_Loader_Internal *loader,
|
||||
Emile_Image_Property *prop,
|
||||
void *map, size_t length,
|
||||
int *error)
|
||||
{
|
||||
|
||||
if (!evas_image_load_file_head_heif_init(loader, prop, map, length, error))
|
||||
return EINA_FALSE;
|
||||
|
||||
heif_image_handle_release_f(loader->handle);
|
||||
heif_context_free_f(loader->ctx);
|
||||
|
||||
return EINA_TRUE;
|
||||
}
|
||||
|
||||
static Eina_Bool
|
||||
evas_image_load_file_data_heif_internal(Evas_Loader_Internal *loader,
|
||||
Emile_Image_Property *prop,
|
||||
|
@ -111,13 +209,11 @@ evas_image_load_file_data_heif_internal(Evas_Loader_Internal *loader,
|
|||
void *map, size_t length,
|
||||
int *error)
|
||||
{
|
||||
struct heif_context *ctx;
|
||||
struct heif_image_handle *handle;
|
||||
struct heif_image *img;
|
||||
struct heif_error err;
|
||||
const unsigned char *data;
|
||||
unsigned char *dd;
|
||||
unsigned char *ds;
|
||||
unsigned char *plane;
|
||||
int stride;
|
||||
unsigned int x;
|
||||
unsigned int y;
|
||||
|
@ -125,44 +221,13 @@ evas_image_load_file_data_heif_internal(Evas_Loader_Internal *loader,
|
|||
|
||||
ret = EINA_FALSE;
|
||||
|
||||
ctx = loader->ctx;
|
||||
if (!ctx)
|
||||
{
|
||||
ctx = heif_context_alloc();
|
||||
if (!ctx)
|
||||
{
|
||||
INF("cannot allocate heif_context");
|
||||
*error = EVAS_LOAD_ERROR_CORRUPT_FILE;
|
||||
return ret;
|
||||
}
|
||||
if (!evas_image_load_file_head_heif_init(loader, prop, map, length, error))
|
||||
return ret;
|
||||
|
||||
err = heif_context_read_from_memory_without_copy(ctx,
|
||||
map, length, NULL);
|
||||
if (err.code != heif_error_Ok)
|
||||
{
|
||||
INF("%s", err.message);
|
||||
*error = EVAS_LOAD_ERROR_UNKNOWN_FORMAT;
|
||||
heif_context_free(ctx);
|
||||
return ret;
|
||||
}
|
||||
|
||||
err = heif_context_get_primary_image_handle(ctx, &handle);
|
||||
if (err.code != heif_error_Ok)
|
||||
{
|
||||
INF("%s", err.message);
|
||||
*error = EVAS_LOAD_ERROR_UNKNOWN_FORMAT;
|
||||
heif_image_handle_release(handle);
|
||||
heif_context_free(ctx);
|
||||
return ret;
|
||||
}
|
||||
|
||||
loader->ctx = ctx;
|
||||
}
|
||||
|
||||
err = heif_decode_image(handle, &img, heif_colorspace_RGB,
|
||||
prop->alpha ? heif_chroma_interleaved_RGBA
|
||||
: heif_chroma_interleaved_RGB,
|
||||
NULL);
|
||||
err = heif_decode_image_f(loader->handle, &img, heif_colorspace_RGB,
|
||||
prop->alpha ? heif_chroma_interleaved_RGBA
|
||||
: heif_chroma_interleaved_RGB,
|
||||
NULL);
|
||||
|
||||
if (err.code != heif_error_Ok)
|
||||
{
|
||||
|
@ -171,39 +236,39 @@ evas_image_load_file_data_heif_internal(Evas_Loader_Internal *loader,
|
|||
goto on_error;
|
||||
}
|
||||
|
||||
data = heif_image_get_plane_readonly(img, heif_channel_interleaved, &stride);
|
||||
data = heif_image_get_plane_readonly_f(img, heif_channel_interleaved, &stride);
|
||||
|
||||
dd = (unsigned char *)pixels;
|
||||
ds = (unsigned char *)data;
|
||||
dd = (unsigned char *)pixels;
|
||||
plane = (unsigned char *)data;
|
||||
if (!prop->alpha)
|
||||
{
|
||||
for (y = 0; y < prop->h; y++)
|
||||
{
|
||||
for (x = 0; x < prop->w; x++)
|
||||
{
|
||||
dd[3] = 0xff;
|
||||
dd[0] = ds[2];
|
||||
dd[1] = ds[1];
|
||||
dd[2] = ds[0];
|
||||
ds+=3;
|
||||
dd+=4;
|
||||
}
|
||||
}
|
||||
for (y = 0; y < prop->h; y++, plane += stride)
|
||||
{
|
||||
int from = 0;
|
||||
for (x = 0; x < prop->w; x++, from += 3)
|
||||
{
|
||||
dd[0] = *(plane + from + 2);
|
||||
dd[1] = *(plane + from + 1);
|
||||
dd[2] = *(plane + from + 0);
|
||||
dd[3] = 0xff;
|
||||
dd += 4;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for (y = 0; y < prop->h; y++)
|
||||
{
|
||||
for (x = 0; x < prop->w; x++)
|
||||
{
|
||||
dd[0] = ds[2];
|
||||
dd[1] = ds[1];
|
||||
dd[2] = ds[0];
|
||||
dd[3] = ds[3];
|
||||
ds+=4;
|
||||
dd+=4;
|
||||
}
|
||||
}
|
||||
for (y = 0; y < prop->h; y++, plane += stride)
|
||||
{
|
||||
int from = 0;
|
||||
for (x = 0; x < prop->w; x++, from += 4)
|
||||
{
|
||||
dd[0] = *(plane + from + 2);
|
||||
dd[1] = *(plane + from + 1);
|
||||
dd[2] = *(plane + from + 0);
|
||||
dd[3] = *(plane + from + 3);
|
||||
dd += 4;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ret = EINA_TRUE;
|
||||
|
@ -243,12 +308,10 @@ evas_image_load_file_close_heif(void *loader_data)
|
|||
Evas_Loader_Internal *loader;
|
||||
|
||||
loader = loader_data;
|
||||
/*
|
||||
* in case _head() fails (because the file is not an heif one),
|
||||
* loader is not filled and loader->ctx is NULL
|
||||
*/
|
||||
if (loader->handle)
|
||||
heif_image_handle_release_f(loader->handle);
|
||||
if (loader->ctx)
|
||||
heif_context_free(loader->ctx);
|
||||
heif_context_free_f(loader->ctx);
|
||||
free(loader_data);
|
||||
}
|
||||
|
||||
|
@ -340,12 +403,60 @@ module_open(Evas_Module *em)
|
|||
|
||||
em->functions = (void *)(&evas_image_load_heif_func);
|
||||
|
||||
#if defined (_WIN32)
|
||||
LOAD("libheif-1.dll");
|
||||
LOAD("libheif.dll");
|
||||
#elif defined (_CYGWIN__)
|
||||
LOAD("cygheif-1.dll");
|
||||
#elif defined(__APPLE__) && defined(__MACH__)
|
||||
LOAD("libheif.1.dylib");
|
||||
#else
|
||||
LOAD("libheif.so.1");
|
||||
#endif
|
||||
|
||||
if (!_evas_loader_heif_mod)
|
||||
{
|
||||
EINA_LOG_ERR("Can not open libheif shared library.");
|
||||
goto error;
|
||||
}
|
||||
|
||||
SYM(heif_check_filetype);
|
||||
SYM(heif_context_alloc);
|
||||
SYM(heif_context_free);
|
||||
SYM(heif_context_get_primary_image_handle);
|
||||
SYM(heif_context_read_from_memory_without_copy);
|
||||
SYM(heif_decode_image);
|
||||
SYM(heif_image_get_plane_readonly);
|
||||
SYM(heif_image_handle_get_height);
|
||||
SYM(heif_image_handle_get_width);
|
||||
SYM(heif_image_handle_has_alpha_channel);
|
||||
SYM(heif_image_handle_release);
|
||||
|
||||
heif_init_f = eina_module_symbol_get(_evas_loader_heif_mod, "heif_init");
|
||||
heif_deinit_f = eina_module_symbol_get(_evas_loader_heif_mod, "heif_deinit");
|
||||
|
||||
if (heif_init_f)
|
||||
{
|
||||
heif_init_f(NULL);
|
||||
}
|
||||
|
||||
return 1;
|
||||
|
||||
error:
|
||||
eina_log_domain_unregister(_evas_loader_heif_log_dom);
|
||||
_evas_loader_heif_log_dom = -1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void
|
||||
module_close(Evas_Module *em EINA_UNUSED)
|
||||
{
|
||||
if (heif_deinit_f)
|
||||
heif_deinit_f();
|
||||
|
||||
if (_evas_loader_heif_mod)
|
||||
eina_module_free(_evas_loader_heif_mod);
|
||||
|
||||
if (_evas_loader_heif_log_dom >= 0)
|
||||
{
|
||||
eina_log_domain_unregister(_evas_loader_heif_log_dom);
|
||||
|
|
|
@ -92,7 +92,6 @@ evas_image_load_file_head_jxl_internal(Evas_Loader_Internal *loader,
|
|||
JXL_DEC_FRAME);
|
||||
if (st != JXL_DEC_SUCCESS)
|
||||
{
|
||||
ERR("Can not subscribe to JXL events");
|
||||
*error = EVAS_LOAD_ERROR_GENERIC;
|
||||
goto destroy_decoder;
|
||||
}
|
||||
|
@ -100,7 +99,6 @@ evas_image_load_file_head_jxl_internal(Evas_Loader_Internal *loader,
|
|||
st = JxlDecoderSetInput(decoder, map, length);
|
||||
if (st != JXL_DEC_SUCCESS)
|
||||
{
|
||||
ERR("Can not set JXL input");
|
||||
*error = EVAS_LOAD_ERROR_GENERIC;
|
||||
goto destroy_decoder;
|
||||
}
|
||||
|
@ -111,7 +109,6 @@ evas_image_load_file_head_jxl_internal(Evas_Loader_Internal *loader,
|
|||
st = JxlDecoderProcessInput(decoder);
|
||||
if (st != JXL_DEC_BASIC_INFO)
|
||||
{
|
||||
ERR("Can not set JXL input (JXL_DEC_BASIC_INFO): %d", st);
|
||||
*error = EVAS_LOAD_ERROR_GENERIC;
|
||||
goto release_input;
|
||||
}
|
||||
|
@ -119,7 +116,6 @@ evas_image_load_file_head_jxl_internal(Evas_Loader_Internal *loader,
|
|||
s = JxlDecoderGetBasicInfo(decoder, &basic_info);
|
||||
if (s != JXL_DEC_SUCCESS)
|
||||
{
|
||||
ERR("Can not retrieve basic info");
|
||||
*error = EVAS_LOAD_ERROR_GENERIC;
|
||||
goto release_input;
|
||||
}
|
||||
|
@ -164,7 +160,6 @@ evas_image_load_file_head_jxl_internal(Evas_Loader_Internal *loader,
|
|||
st = JxlDecoderProcessInput(decoder);
|
||||
if (st != JXL_DEC_SUCCESS)
|
||||
{
|
||||
ERR("Can not set JXL input (JXL_DEC_SUCCESS)");
|
||||
*error = EVAS_LOAD_ERROR_GENERIC;
|
||||
goto release_input;
|
||||
}
|
||||
|
@ -229,7 +224,6 @@ evas_image_load_file_data_jxl_internal(Evas_Loader_Internal *loader,
|
|||
runner);
|
||||
if (st != JXL_DEC_SUCCESS)
|
||||
{
|
||||
ERR("Can not set JXL runner");
|
||||
*error = EVAS_LOAD_ERROR_GENERIC;
|
||||
goto on_error;
|
||||
}
|
||||
|
@ -242,7 +236,6 @@ evas_image_load_file_data_jxl_internal(Evas_Loader_Internal *loader,
|
|||
st = JxlDecoderSetInput(decoder, map, length);
|
||||
if (st != JXL_DEC_SUCCESS)
|
||||
{
|
||||
ERR("Can not set JXL input");
|
||||
*error = EVAS_LOAD_ERROR_GENERIC;
|
||||
goto on_error;
|
||||
}
|
||||
|
@ -253,7 +246,6 @@ evas_image_load_file_data_jxl_internal(Evas_Loader_Internal *loader,
|
|||
JXL_DEC_FULL_IMAGE);
|
||||
if (st != JXL_DEC_SUCCESS)
|
||||
{
|
||||
ERR("Can not subscribe to JXL events");
|
||||
*error = EVAS_LOAD_ERROR_GENERIC;
|
||||
goto on_error;
|
||||
}
|
||||
|
@ -286,7 +278,6 @@ evas_image_load_file_data_jxl_internal(Evas_Loader_Internal *loader,
|
|||
|
||||
if (st != JXL_DEC_NEED_IMAGE_OUT_BUFFER)
|
||||
{
|
||||
ERR("Can not process JXL_DEC_NEED_IMAGE_OUT_BUFFER events (st=%d)", st);
|
||||
*error = EVAS_LOAD_ERROR_GENERIC;
|
||||
goto on_error;
|
||||
}
|
||||
|
@ -296,7 +287,6 @@ evas_image_load_file_data_jxl_internal(Evas_Loader_Internal *loader,
|
|||
&buffer_size);
|
||||
if (st != JXL_DEC_SUCCESS)
|
||||
{
|
||||
ERR("JxlDecoderImageOutBufferSize failed");
|
||||
*error = EVAS_LOAD_ERROR_GENERIC;
|
||||
goto on_error;
|
||||
}
|
||||
|
@ -314,7 +304,6 @@ evas_image_load_file_data_jxl_internal(Evas_Loader_Internal *loader,
|
|||
buffer_size);
|
||||
if (st != JXL_DEC_SUCCESS)
|
||||
{
|
||||
ERR("Can not set image output buffer");
|
||||
*error = EVAS_LOAD_ERROR_GENERIC;
|
||||
goto on_error;
|
||||
}
|
||||
|
@ -322,7 +311,6 @@ evas_image_load_file_data_jxl_internal(Evas_Loader_Internal *loader,
|
|||
st = JxlDecoderProcessInput(decoder);
|
||||
if (st != JXL_DEC_FULL_IMAGE)
|
||||
{
|
||||
ERR("Can not process JXL_DEC_FULL_IMAGE events");
|
||||
*error = EVAS_LOAD_ERROR_GENERIC;
|
||||
goto on_error;
|
||||
}
|
||||
|
|
|
@ -0,0 +1,425 @@
|
|||
#ifdef HAVE_CONFIG_H
|
||||
# include <config.h>
|
||||
#endif
|
||||
|
||||
#include "Evas_Loader.h"
|
||||
#include "evas_common_private.h"
|
||||
|
||||
/*
|
||||
* code based on original qoi.h code (MIT license):
|
||||
* https://github.com/phoboslab/qoi/blob/master/qoi.h
|
||||
* date: 2023 march the 14th
|
||||
*/
|
||||
|
||||
#define QOI_ZEROARR(a) memset((a),0,sizeof(a))
|
||||
|
||||
#define QOI_OP_INDEX 0x00 /* 00xxxxxx */
|
||||
#define QOI_OP_DIFF 0x40 /* 01xxxxxx */
|
||||
#define QOI_OP_LUMA 0x80 /* 10xxxxxx */
|
||||
#define QOI_OP_RUN 0xc0 /* 11xxxxxx */
|
||||
#define QOI_OP_RGB 0xfe /* 11111110 */
|
||||
#define QOI_OP_RGBA 0xff /* 11111111 */
|
||||
|
||||
#define QOI_MASK_2 0xc0 /* 11000000 */
|
||||
|
||||
#define QOI_COLOR_HASH(C) (C.rgba.r*3 + C.rgba.g*5 + C.rgba.b*7 + C.rgba.a*11)
|
||||
|
||||
#define QOI_MAGIC \
|
||||
(((unsigned int)'q') << 24 | ((unsigned int)'o') << 16 | \
|
||||
((unsigned int)'i') << 8 | ((unsigned int)'f'))
|
||||
|
||||
#define QOI_HEADER_SIZE 14
|
||||
|
||||
#define QOI_PIXELS_MAX ((unsigned int)400000000)
|
||||
|
||||
#ifdef ERR
|
||||
# undef ERR
|
||||
#endif
|
||||
#define ERR(...) EINA_LOG_DOM_ERR(_evas_loader_qoi_log_dom, __VA_ARGS__)
|
||||
|
||||
#ifdef WRN
|
||||
# undef WRN
|
||||
#endif
|
||||
#define WRN(...) EINA_LOG_DOM_WARN(_evas_loader_qoi_log_dom, __VA_ARGS__)
|
||||
|
||||
#ifdef INF
|
||||
# undef INF
|
||||
#endif
|
||||
#define INF(...) EINA_LOG_DOM_INFO(_evas_loader_qoi_log_dom, __VA_ARGS__)
|
||||
|
||||
typedef struct _Evas_Loader_Internal Evas_Loader_Internal;
|
||||
struct _Evas_Loader_Internal
|
||||
{
|
||||
Eina_File *f;
|
||||
Evas_Image_Load_Opts *opts;
|
||||
Evas_Image_Animated *animated;
|
||||
};
|
||||
|
||||
typedef union {
|
||||
struct { unsigned char r, g, b, a; } rgba;
|
||||
unsigned int v;
|
||||
} qoi_rgba_t;
|
||||
|
||||
static int _evas_loader_qoi_log_dom = -1;
|
||||
|
||||
static const unsigned char qoi_padding[8] = {0,0,0,0,0,0,0,1};
|
||||
|
||||
static unsigned int read_32(const unsigned char *data, int *p)
|
||||
{
|
||||
unsigned int a = data[(*p)++];
|
||||
unsigned int b = data[(*p)++];
|
||||
unsigned int c = data[(*p)++];
|
||||
unsigned int d = data[(*p)++];
|
||||
return a << 24 | b << 16 | c << 8 | d;
|
||||
}
|
||||
|
||||
static Eina_Bool
|
||||
evas_image_load_file_head_qoi_internal(Evas_Loader_Internal *loader EINA_UNUSED,
|
||||
Emile_Image_Property *prop,
|
||||
void *map, size_t length,
|
||||
int *error)
|
||||
{
|
||||
const unsigned char *bytes;
|
||||
unsigned int magic;
|
||||
unsigned char channels;
|
||||
unsigned char colorspace;
|
||||
int p = 0;
|
||||
Eina_Bool ret;
|
||||
|
||||
ret = EINA_FALSE;
|
||||
prop->w = 0;
|
||||
prop->h = 0;
|
||||
prop->alpha = EINA_FALSE;
|
||||
|
||||
if (length < QOI_HEADER_SIZE + sizeof(qoi_padding))
|
||||
{
|
||||
*error = EVAS_LOAD_ERROR_UNKNOWN_FORMAT;
|
||||
return ret;
|
||||
}
|
||||
|
||||
bytes = (const unsigned char *)map;
|
||||
|
||||
magic = read_32(bytes, &p);
|
||||
if (magic != QOI_MAGIC)
|
||||
{
|
||||
*error = EVAS_LOAD_ERROR_UNKNOWN_FORMAT;
|
||||
return ret;
|
||||
}
|
||||
|
||||
prop->w = read_32(bytes, &p);
|
||||
prop->h = read_32(bytes, &p);
|
||||
if ((prop->w < 1) ||
|
||||
(prop->h < 1) ||
|
||||
(prop->h >= QOI_PIXELS_MAX / prop->w) ||
|
||||
(prop->w > IMG_MAX_SIZE) ||
|
||||
(prop->h > IMG_MAX_SIZE) ||
|
||||
IMG_TOO_BIG(prop->w, prop->h))
|
||||
{
|
||||
*error= EVAS_LOAD_ERROR_GENERIC;
|
||||
return ret;
|
||||
}
|
||||
|
||||
channels = bytes[p++];
|
||||
colorspace = bytes[p++];
|
||||
|
||||
if ((channels < 3) ||
|
||||
(channels > 4) ||
|
||||
(colorspace > 1))
|
||||
{
|
||||
*error = EVAS_LOAD_ERROR_CORRUPT_FILE;
|
||||
return ret;
|
||||
}
|
||||
|
||||
prop->alpha = channels == 4;
|
||||
|
||||
*error = EVAS_LOAD_ERROR_NONE;
|
||||
return EINA_TRUE;
|
||||
}
|
||||
|
||||
static Eina_Bool
|
||||
evas_image_load_file_data_qoi_internal(Evas_Loader_Internal *loader EINA_UNUSED,
|
||||
Emile_Image_Property *prop,
|
||||
void *pixels,
|
||||
void *map, size_t length,
|
||||
int *error)
|
||||
{
|
||||
qoi_rgba_t index[64];
|
||||
const unsigned char *bytes;
|
||||
qoi_rgba_t px;
|
||||
unsigned int *iter;
|
||||
unsigned int magic;
|
||||
unsigned char channels;
|
||||
unsigned char colorspace;
|
||||
int p = 0;
|
||||
int run = 0;
|
||||
int chunks_len;
|
||||
size_t px_len;
|
||||
size_t px_pos;
|
||||
Eina_Bool ret;
|
||||
|
||||
ret = EINA_FALSE;
|
||||
prop->w = 0;
|
||||
prop->h = 0;
|
||||
prop->alpha = EINA_FALSE;
|
||||
|
||||
if (length < QOI_HEADER_SIZE + sizeof(qoi_padding))
|
||||
{
|
||||
*error = EVAS_LOAD_ERROR_UNKNOWN_FORMAT;
|
||||
return ret;
|
||||
}
|
||||
|
||||
bytes = (const unsigned char *)map;
|
||||
|
||||
magic = read_32(bytes, &p);
|
||||
if (magic != QOI_MAGIC)
|
||||
{
|
||||
*error = EVAS_LOAD_ERROR_UNKNOWN_FORMAT;
|
||||
return ret;
|
||||
}
|
||||
|
||||
prop->w = read_32(bytes, &p);
|
||||
prop->h = read_32(bytes, &p);
|
||||
if ((prop->w < 1) ||
|
||||
(prop->h < 1) ||
|
||||
(prop->h >= QOI_PIXELS_MAX / prop->w) ||
|
||||
(prop->w > IMG_MAX_SIZE) ||
|
||||
(prop->h > IMG_MAX_SIZE) ||
|
||||
IMG_TOO_BIG(prop->w, prop->h))
|
||||
{
|
||||
*error= EVAS_LOAD_ERROR_GENERIC;
|
||||
return ret;
|
||||
}
|
||||
|
||||
channels = bytes[p++];
|
||||
colorspace = bytes[p++];
|
||||
|
||||
if ((channels < 3) ||
|
||||
(channels > 4) ||
|
||||
(colorspace > 1))
|
||||
{
|
||||
*error = EVAS_LOAD_ERROR_CORRUPT_FILE;
|
||||
return ret;
|
||||
}
|
||||
|
||||
prop->alpha = channels == 4;
|
||||
|
||||
px_len = prop->w * prop->h * channels;
|
||||
|
||||
QOI_ZEROARR(index);
|
||||
px.rgba.r = 0;
|
||||
px.rgba.g = 0;
|
||||
px.rgba.b = 0;
|
||||
px.rgba.a = 255;
|
||||
|
||||
iter = pixels;
|
||||
chunks_len = length - (int)sizeof(qoi_padding);
|
||||
for (px_pos = 0; px_pos < px_len; px_pos += channels, iter++)
|
||||
{
|
||||
if (run > 0)
|
||||
{
|
||||
run--;
|
||||
}
|
||||
else if (p < chunks_len)
|
||||
{
|
||||
int b1 = bytes[p++];
|
||||
|
||||
if (b1 == QOI_OP_RGB)
|
||||
{
|
||||
px.rgba.r = bytes[p++];
|
||||
px.rgba.g = bytes[p++];
|
||||
px.rgba.b = bytes[p++];
|
||||
}
|
||||
else if (b1 == QOI_OP_RGBA)
|
||||
{
|
||||
px.rgba.r = bytes[p++];
|
||||
px.rgba.g = bytes[p++];
|
||||
px.rgba.b = bytes[p++];
|
||||
px.rgba.a = bytes[p++];
|
||||
}
|
||||
else if ((b1 & QOI_MASK_2) == QOI_OP_INDEX)
|
||||
{
|
||||
px = index[b1];
|
||||
}
|
||||
else if ((b1 & QOI_MASK_2) == QOI_OP_DIFF)
|
||||
{
|
||||
px.rgba.r += ((b1 >> 4) & 0x03) - 2;
|
||||
px.rgba.g += ((b1 >> 2) & 0x03) - 2;
|
||||
px.rgba.b += ( b1 & 0x03) - 2;
|
||||
}
|
||||
else if ((b1 & QOI_MASK_2) == QOI_OP_LUMA)
|
||||
{
|
||||
int b2 = bytes[p++];
|
||||
int vg = (b1 & 0x3f) - 32;
|
||||
px.rgba.r += vg - 8 + ((b2 >> 4) & 0x0f);
|
||||
px.rgba.g += vg;
|
||||
px.rgba.b += vg - 8 + (b2 & 0x0f);
|
||||
}
|
||||
else if ((b1 & QOI_MASK_2) == QOI_OP_RUN)
|
||||
{
|
||||
run = (b1 & 0x3f);
|
||||
}
|
||||
|
||||
index[QOI_COLOR_HASH(px) % 64] = px;
|
||||
}
|
||||
|
||||
if (prop->alpha)
|
||||
*iter = (px.rgba.a << 24) |
|
||||
(((px.rgba.r * px.rgba.a) / 255) << 16) |
|
||||
(((px.rgba.g * px.rgba.a) / 255) << 8) |
|
||||
(((px.rgba.b * px.rgba.a) / 255));
|
||||
else
|
||||
*iter = (255 << 24) |
|
||||
(px.rgba.r << 16) |
|
||||
(px.rgba.g << 8) |
|
||||
(px.rgba.b);
|
||||
}
|
||||
|
||||
*error = EVAS_LOAD_ERROR_NONE;
|
||||
return EINA_TRUE;
|
||||
}
|
||||
|
||||
static void *
|
||||
evas_image_load_file_open_qoi(Eina_File *f, Eina_Stringshare *key EINA_UNUSED,
|
||||
Evas_Image_Load_Opts *opts,
|
||||
Evas_Image_Animated *animated EINA_UNUSED,
|
||||
int *error)
|
||||
{
|
||||
Evas_Loader_Internal *loader;
|
||||
|
||||
loader = calloc(1, sizeof (Evas_Loader_Internal));
|
||||
if (!loader)
|
||||
{
|
||||
*error = EVAS_LOAD_ERROR_RESOURCE_ALLOCATION_FAILED;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
loader->f = f;
|
||||
loader->opts = opts;
|
||||
|
||||
return loader;
|
||||
}
|
||||
|
||||
static void
|
||||
evas_image_load_file_close_qoi(void *loader_data)
|
||||
{
|
||||
free(loader_data);
|
||||
}
|
||||
|
||||
static Eina_Bool
|
||||
evas_image_load_file_head_qoi(void *loader_data,
|
||||
Evas_Image_Property *prop,
|
||||
int *error)
|
||||
{
|
||||
Evas_Loader_Internal *loader = loader_data;
|
||||
Eina_File *f;
|
||||
void *map;
|
||||
Eina_Bool val;
|
||||
|
||||
f = loader->f;
|
||||
|
||||
map = eina_file_map_all(f, EINA_FILE_RANDOM);
|
||||
if (!map)
|
||||
{
|
||||
*error = EVAS_LOAD_ERROR_DOES_NOT_EXIST;
|
||||
return EINA_FALSE;
|
||||
}
|
||||
|
||||
val = evas_image_load_file_head_qoi_internal(loader,
|
||||
(Emile_Image_Property *)prop,
|
||||
map, eina_file_size_get(f),
|
||||
error);
|
||||
|
||||
eina_file_map_free(f, map);
|
||||
|
||||
return val;
|
||||
}
|
||||
|
||||
static Eina_Bool
|
||||
evas_image_load_file_data_qoi(void *loader_data,
|
||||
Evas_Image_Property *prop,
|
||||
void *pixels,
|
||||
int *error)
|
||||
{
|
||||
Evas_Loader_Internal *loader;
|
||||
Eina_File *f;
|
||||
void *map;
|
||||
Eina_Bool val = EINA_FALSE;
|
||||
|
||||
loader = (Evas_Loader_Internal *)loader_data;
|
||||
f = loader->f;
|
||||
|
||||
map = eina_file_map_all(f, EINA_FILE_WILLNEED);
|
||||
if (!map)
|
||||
{
|
||||
*error = EVAS_LOAD_ERROR_DOES_NOT_EXIST;
|
||||
goto on_error;
|
||||
}
|
||||
|
||||
val = evas_image_load_file_data_qoi_internal(loader,
|
||||
(Emile_Image_Property *)prop,
|
||||
pixels,
|
||||
map, eina_file_size_get(f),
|
||||
error);
|
||||
|
||||
eina_file_map_free(f, map);
|
||||
|
||||
on_error:
|
||||
return val;
|
||||
}
|
||||
|
||||
static Evas_Image_Load_Func evas_image_load_qoi_func =
|
||||
{
|
||||
EVAS_IMAGE_LOAD_VERSION,
|
||||
evas_image_load_file_open_qoi,
|
||||
evas_image_load_file_close_qoi,
|
||||
evas_image_load_file_head_qoi,
|
||||
NULL,
|
||||
evas_image_load_file_data_qoi,
|
||||
NULL,
|
||||
EINA_TRUE,
|
||||
EINA_FALSE
|
||||
};
|
||||
|
||||
static int
|
||||
module_open(Evas_Module *em)
|
||||
{
|
||||
if (!em) return 0;
|
||||
|
||||
_evas_loader_qoi_log_dom = eina_log_domain_register("evas-qoi", EINA_COLOR_BLUE);
|
||||
if (_evas_loader_qoi_log_dom < 0)
|
||||
{
|
||||
EINA_LOG_ERR("Can not create a module log domain.");
|
||||
return 0;
|
||||
}
|
||||
|
||||
em->functions = (void *)(&evas_image_load_qoi_func);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static void
|
||||
module_close(Evas_Module *em EINA_UNUSED)
|
||||
{
|
||||
if (_evas_loader_qoi_log_dom >= 0)
|
||||
{
|
||||
eina_log_domain_unregister(_evas_loader_qoi_log_dom);
|
||||
_evas_loader_qoi_log_dom = -1;
|
||||
}
|
||||
}
|
||||
|
||||
static Evas_Module_Api evas_modapi =
|
||||
{
|
||||
EVAS_MODULE_API_VERSION,
|
||||
"qoi",
|
||||
"none",
|
||||
{
|
||||
module_open,
|
||||
module_close
|
||||
}
|
||||
};
|
||||
|
||||
EVAS_MODULE_DEFINE(EVAS_MODULE_TYPE_IMAGE_LOADER, image_loader, qoi);
|
||||
|
||||
#ifndef EVAS_STATIC_BUILD_QOI
|
||||
EVAS_EINA_MODULE_DEFINE(image_loader, qoi);
|
||||
#endif
|
|
@ -0,0 +1,273 @@
|
|||
#ifdef HAVE_CONFIG_H
|
||||
# include <config.h>
|
||||
#endif
|
||||
|
||||
#include "evas_common_private.h"
|
||||
#include "evas_private.h"
|
||||
|
||||
/*
|
||||
* code based on original qoi.h code (MIT license):
|
||||
* https://github.com/phoboslab/qoi/blob/master/qoi.h
|
||||
* date: 2023 march the 14th
|
||||
*/
|
||||
|
||||
#define QOI_SRGB 0
|
||||
|
||||
#define QOI_ZEROARR(a) memset((a),0,sizeof(a))
|
||||
|
||||
#define QOI_OP_INDEX 0x00 /* 00xxxxxx */
|
||||
#define QOI_OP_DIFF 0x40 /* 01xxxxxx */
|
||||
#define QOI_OP_LUMA 0x80 /* 10xxxxxx */
|
||||
#define QOI_OP_RUN 0xc0 /* 11xxxxxx */
|
||||
#define QOI_OP_RGB 0xfe /* 11111110 */
|
||||
#define QOI_OP_RGBA 0xff /* 11111111 */
|
||||
|
||||
#define QOI_COLOR_HASH(C) (C.rgba.r*3 + C.rgba.g*5 + C.rgba.b*7 + C.rgba.a*11)
|
||||
|
||||
#define QOI_MAGIC \
|
||||
(((unsigned int)'q') << 24 | ((unsigned int)'o') << 16 | \
|
||||
((unsigned int)'i') << 8 | ((unsigned int)'f'))
|
||||
|
||||
#define QOI_HEADER_SIZE 14
|
||||
|
||||
#define QOI_PIXELS_MAX ((unsigned int)400000000)
|
||||
|
||||
typedef union {
|
||||
struct { unsigned char r, g, b, a; } rgba;
|
||||
unsigned int v;
|
||||
} qoi_rgba_t;
|
||||
|
||||
static const unsigned char qoi_padding[8] = {0,0,0,0,0,0,0,1};
|
||||
|
||||
static int
|
||||
save_image_qoi(RGBA_Image *im, const char *file, int quality EINA_UNUSED)
|
||||
{
|
||||
qoi_rgba_t index[64];
|
||||
qoi_rgba_t px;
|
||||
qoi_rgba_t px_prev;
|
||||
FILE *f;
|
||||
unsigned char *iter;
|
||||
unsigned int channels;
|
||||
unsigned int colorspace;
|
||||
unsigned int v;
|
||||
int run;
|
||||
int px_len;
|
||||
int px_end;
|
||||
int px_pos;
|
||||
int i;
|
||||
int ret = 0;
|
||||
|
||||
if (!im || !im->image.data || !file || !*file)
|
||||
return ret;
|
||||
|
||||
if (im->cache_entry.h >= QOI_PIXELS_MAX / im->cache_entry.w)
|
||||
return ret;
|
||||
|
||||
f = fopen(file, "wb");
|
||||
if (!f)
|
||||
return ret;
|
||||
|
||||
v = (0xff000000 & QOI_MAGIC) >> 24;
|
||||
if (fwrite(&v, 1, 1, f) != 1) goto close_f;
|
||||
v = (0x00ff0000 & QOI_MAGIC) >> 16;
|
||||
if (fwrite(&v, 1, 1, f) != 1) goto close_f;
|
||||
v = (0x0000ff00 & QOI_MAGIC) >> 8;
|
||||
if (fwrite(&v, 1, 1, f) != 1) goto close_f;
|
||||
v = (0x000000ff & QOI_MAGIC);
|
||||
if (fwrite(&v, 1, 1, f) != 1) goto close_f;
|
||||
|
||||
v = (0xff000000 & im->cache_entry.w) >> 24;
|
||||
if (fwrite(&v, 1, 1, f) != 1) goto close_f;
|
||||
v = (0x00ff0000 & im->cache_entry.w) >> 16;
|
||||
if (fwrite(&v, 1, 1, f) != 1) goto close_f;
|
||||
v = (0x0000ff00 & im->cache_entry.w) >> 8;
|
||||
if (fwrite(&v, 1, 1, f) != 1) goto close_f;
|
||||
v = (0x000000ff & im->cache_entry.w);
|
||||
if (fwrite(&v, 1, 1, f) != 1) goto close_f;
|
||||
|
||||
v = (0xff000000 & im->cache_entry.h) >> 24;
|
||||
if (fwrite(&v, 1, 1, f) != 1) goto close_f;
|
||||
v = (0x00ff0000 & im->cache_entry.h) >> 16;
|
||||
if (fwrite(&v, 1, 1, f) != 1) goto close_f;
|
||||
v = (0x0000ff00 & im->cache_entry.h) >> 8;
|
||||
if (fwrite(&v, 1, 1, f) != 1) goto close_f;
|
||||
v = (0x000000ff & im->cache_entry.h);
|
||||
if (fwrite(&v, 1, 1, f) != 1) goto close_f;
|
||||
|
||||
channels = 4;
|
||||
if (fwrite(&channels, 1, 1, f) != 1) goto close_f;
|
||||
|
||||
colorspace = QOI_SRGB;
|
||||
if (fwrite(&colorspace, 1, 1, f) != 1) goto close_f;
|
||||
|
||||
QOI_ZEROARR(index);
|
||||
|
||||
run = 0;
|
||||
px_prev.rgba.r = 0;
|
||||
px_prev.rgba.g = 0;
|
||||
px_prev.rgba.b = 0;
|
||||
px_prev.rgba.a = 255;
|
||||
px = px_prev;
|
||||
|
||||
px_len = im->cache_entry.w * im->cache_entry.h * channels;
|
||||
px_end = px_len - channels;
|
||||
|
||||
iter = (unsigned char *)im->image.data;
|
||||
for (px_pos = 0; px_pos < px_len; px_pos += channels, iter +=4)
|
||||
{
|
||||
px.rgba.a = *(iter + 3);
|
||||
if (px.rgba.a == 0)
|
||||
{
|
||||
px.rgba.b = *(iter + 0);
|
||||
px.rgba.g = *(iter + 1);
|
||||
px.rgba.r = *(iter + 2);
|
||||
}
|
||||
else
|
||||
{
|
||||
px.rgba.b = *(iter + 0) * 255 / px.rgba.a;
|
||||
px.rgba.g = *(iter + 1) * 255 / px.rgba.a;
|
||||
px.rgba.r = *(iter + 2) * 255 / px.rgba.a;
|
||||
}
|
||||
|
||||
if (px.v == px_prev.v)
|
||||
{
|
||||
run++;
|
||||
if (run == 62 || px_pos == px_end)
|
||||
{
|
||||
unsigned char val = QOI_OP_RUN | (run - 1);
|
||||
if (fwrite(&val, 1, 1, f) != 1) goto close_f;
|
||||
run = 0;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
int index_pos;
|
||||
|
||||
if (run > 0)
|
||||
{
|
||||
unsigned char val = QOI_OP_RUN | (run - 1);
|
||||
if (fwrite(&val, 1, 1, f) != 1) goto close_f;
|
||||
run = 0;
|
||||
}
|
||||
|
||||
index_pos = QOI_COLOR_HASH(px) % 64;
|
||||
|
||||
if (index[index_pos].v == px.v)
|
||||
{
|
||||
unsigned char val = QOI_OP_INDEX | index_pos;
|
||||
if (fwrite(&val, 1, 1, f) != 1) goto close_f;
|
||||
}
|
||||
else
|
||||
{
|
||||
index[index_pos] = px;
|
||||
|
||||
if (px.rgba.a == px_prev.rgba.a)
|
||||
{
|
||||
signed char vr = px.rgba.r - px_prev.rgba.r;
|
||||
signed char vg = px.rgba.g - px_prev.rgba.g;
|
||||
signed char vb = px.rgba.b - px_prev.rgba.b;
|
||||
|
||||
signed char vg_r = vr - vg;
|
||||
signed char vg_b = vb - vg;
|
||||
|
||||
if (vr > -3 && vr < 2 &&
|
||||
vg > -3 && vg < 2 &&
|
||||
vb > -3 && vb < 2)
|
||||
{
|
||||
unsigned char val = QOI_OP_DIFF | (vr + 2) << 4 | (vg + 2) << 2 | (vb + 2);
|
||||
if (fwrite(&val, 1, 1, f) != 1) goto close_f;
|
||||
}
|
||||
else if (vg_r > -9 && vg_r < 8 &&
|
||||
vg > -33 && vg < 32 &&
|
||||
vg_b > -9 && vg_b < 8)
|
||||
{
|
||||
unsigned char val;
|
||||
|
||||
val = QOI_OP_LUMA | (vg + 32);
|
||||
if (fwrite(&val, 1, 1, f) != 1) goto close_f;
|
||||
|
||||
val = (vg_r + 8) << 4 | (vg_b + 8);
|
||||
if (fwrite(&val, 1, 1, f) != 1) goto close_f;
|
||||
}
|
||||
else
|
||||
{
|
||||
unsigned char val;
|
||||
|
||||
val = QOI_OP_RGB;
|
||||
if (fwrite(&val, 1, 1, f) != 1) goto close_f;
|
||||
if (fwrite(&px.rgba.r, 1, 1, f) != 1) goto close_f;
|
||||
if (fwrite(&px.rgba.g, 1, 1, f) != 1) goto close_f;
|
||||
if (fwrite(&px.rgba.b, 1, 1, f) != 1) goto close_f;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
unsigned char val;
|
||||
|
||||
val = QOI_OP_RGBA;
|
||||
if (fwrite(&val, 1, 1, f) != 1) goto close_f;
|
||||
if (fwrite(&px.rgba.r, 1, 1, f) != 1) goto close_f;
|
||||
if (fwrite(&px.rgba.g, 1, 1, f) != 1) goto close_f;
|
||||
if (fwrite(&px.rgba.b, 1, 1, f) != 1) goto close_f;
|
||||
if (fwrite(&px.rgba.a, 1, 1, f) != 1) goto close_f;
|
||||
}
|
||||
}
|
||||
}
|
||||
px_prev = px;
|
||||
}
|
||||
|
||||
for (i = 0; i < (int)sizeof(qoi_padding); i++)
|
||||
{
|
||||
if (fwrite(&qoi_padding[i], 1, 1, f) != 1) goto close_f;
|
||||
}
|
||||
|
||||
ret = 1;
|
||||
|
||||
close_f:
|
||||
fclose(f);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
static int evas_image_save_file_qoi(RGBA_Image *im, const char *file, const char *key EINA_UNUSED,
|
||||
int quality, int compress EINA_UNUSED, const char *encoding EINA_UNUSED)
|
||||
{
|
||||
return save_image_qoi(im, file, quality);
|
||||
}
|
||||
|
||||
|
||||
static Evas_Image_Save_Func evas_image_save_qoi_func =
|
||||
{
|
||||
evas_image_save_file_qoi
|
||||
};
|
||||
|
||||
static int
|
||||
module_open(Evas_Module *em)
|
||||
{
|
||||
if (!em) return 0;
|
||||
em->functions = (void *)(&evas_image_save_qoi_func);
|
||||
return 1;
|
||||
}
|
||||
|
||||
static void
|
||||
module_close(Evas_Module *em EINA_UNUSED)
|
||||
{
|
||||
}
|
||||
|
||||
static Evas_Module_Api evas_modapi =
|
||||
{
|
||||
EVAS_MODULE_API_VERSION,
|
||||
"qoi",
|
||||
"none",
|
||||
{
|
||||
module_open,
|
||||
module_close
|
||||
}
|
||||
};
|
||||
|
||||
EVAS_MODULE_DEFINE(EVAS_MODULE_TYPE_IMAGE_SAVER, image_saver, qoi);
|
||||
|
||||
#ifndef EVAS_STATIC_BUILD_QOI
|
||||
EVAS_EINA_MODULE_DEFINE(image_saver, qoi);
|
||||
#endif
|
Loading…
Reference in New Issue