forked from enlightenment/efl
Compare commits
78 Commits
master
...
devs/devil
Author | SHA1 | Date |
---|---|---|
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 |
|
@ -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;
|
||||
|
|
|
@ -498,44 +498,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;
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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;
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -1,60 +1,47 @@
|
|||
#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 +55,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,9 +144,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;
|
||||
|
||||
return _ecore_drm2_init_count;
|
||||
|
@ -204,8 +174,7 @@ ecore_drm2_shutdown(void)
|
|||
|
||||
if (--_ecore_drm2_init_count != 0) return _ecore_drm2_init_count;
|
||||
|
||||
ECORE_DRM2_EVENT_OUTPUT_CHANGED = -1;
|
||||
ECORE_DRM2_EVENT_ACTIVATE = -1;
|
||||
if (_drm_lib) dlclose(_drm_lib);
|
||||
|
||||
eina_log_domain_unregister(_ecore_drm2_log_dom);
|
||||
_ecore_drm2_log_dom = -1;
|
||||
|
@ -217,18 +186,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,853 @@
|
|||
#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)
|
||||
{
|
||||
Ecore_Drm2_Display_State *dstate;
|
||||
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;
|
||||
}
|
||||
|
||||
dstate = disp->state.current;
|
||||
|
||||
/* 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 */
|
||||
dstate->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->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 EINA_UNUSED, int y EINA_UNUSED)
|
||||
{
|
||||
EINA_SAFETY_ON_NULL_RETURN(disp);
|
||||
EINA_SAFETY_ON_NULL_RETURN(mode);
|
||||
EINA_SAFETY_ON_NULL_RETURN(disp->crtc);
|
||||
|
||||
/* TODO, FIXME */
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
EINA_SAFETY_ON_NULL_RETURN(disp);
|
||||
|
||||
if (disp->state.current->enabled == enabled) return;
|
||||
|
||||
/* TODO, FIXME */
|
||||
|
||||
disp->state.pending->enabled = enabled;
|
||||
disp->state.pending->changes |= ECORE_DRM2_DISPLAY_STATE_ENABLED;
|
||||
}
|
||||
|
||||
EAPI unsigned int
|
||||
ecore_drm2_display_crtc_get(Ecore_Drm2_Display *disp)
|
||||
{
|
||||
EINA_SAFETY_ON_NULL_RETURN_VAL(disp, 0);
|
||||
EINA_SAFETY_ON_NULL_RETURN_VAL(disp->crtc, 0);
|
||||
return disp->crtc->id;
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
EINA_SAFETY_ON_NULL_RETURN(disp);
|
||||
if (disp->state.current->primary == primary) return;
|
||||
|
||||
/* TODO, FIXME */
|
||||
|
||||
disp->state.pending->primary = primary;
|
||||
disp->state.pending->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)
|
||||
{
|
||||
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;
|
||||
|
||||
switch (disp->state.current->rotation)
|
||||
{
|
||||
case ECORE_DRM2_ROTATION_90:
|
||||
case ECORE_DRM2_ROTATION_270:
|
||||
if (w) *w = disp->state.current->mode->height;
|
||||
if (h) *h = disp->state.current->mode->width;
|
||||
break;
|
||||
case ECORE_DRM2_ROTATION_NORMAL:
|
||||
case ECORE_DRM2_ROTATION_180:
|
||||
default:
|
||||
if (w) *w = disp->state.current->mode->width;
|
||||
if (h) *h = disp->state.current->mode->height;
|
||||
break;
|
||||
}
|
||||
|
||||
if (refresh) *refresh = disp->state.current->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)
|
||||
{
|
||||
EINA_SAFETY_ON_NULL_RETURN(disp);
|
||||
|
||||
if (disp->state.current->rotation == rotation) return;
|
||||
|
||||
/* TODO, FIXME */
|
||||
|
||||
disp->state.pending->rotation = rotation;
|
||||
disp->state.pending->changes |= ECORE_DRM2_DISPLAY_STATE_ROTATION;
|
||||
}
|
|
@ -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,397 @@
|
|||
#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 */
|
||||
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,106 @@
|
|||
# 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_Changes;
|
||||
|
||||
typedef struct _Ecore_Drm2_Atomic_Blob
|
||||
{
|
||||
|
@ -72,152 +115,134 @@ 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;
|
||||
uint16_t gamma;
|
||||
uint64_t rotation;
|
||||
double backlight;
|
||||
|
||||
# ifndef DRM_CAP_CURSOR_WIDTH
|
||||
# define DRM_CAP_CURSOR_WIDTH 0x8
|
||||
# endif
|
||||
Ecore_Drm2_Display_Mode *mode;
|
||||
|
||||
# ifndef DRM_CAP_CURSOR_HEIGHT
|
||||
# define DRM_CAP_CURSOR_HEIGHT 0x9
|
||||
# endif
|
||||
|
||||
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_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 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,54 +250,68 @@ 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;
|
||||
|
||||
struct
|
||||
{
|
||||
const char *to;
|
||||
Ecore_Drm2_Relative_Mode mode;
|
||||
} relative;
|
||||
Ecore_Drm2_Display_State *current;
|
||||
Ecore_Drm2_Display_State *pending;
|
||||
} state;
|
||||
|
||||
drmModeCrtcPtr ocrtc;
|
||||
Ecore_Drm2_Device *dev;
|
||||
Ecore_Drm2_Crtc *crtc;
|
||||
Ecore_Drm2_Connector *conn;
|
||||
|
||||
/* prep is for state we're preparing and have never
|
||||
* attempted to commit */
|
||||
Ecore_Drm2_Output_State prep;
|
||||
|
||||
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 +319,66 @@ 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_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'
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
||||
|
|
|
@ -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',
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
engines = [
|
||||
['cocoa', ['cocoa']],
|
||||
['drm', ['drm']],
|
||||
# ['drm', ['drm']],
|
||||
['fb', ['fb']],
|
||||
['sdl', ['sdl']],
|
||||
['wayland', ['wl']],
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in New Issue