Compare commits

...

78 Commits

Author SHA1 Message Date
Christopher Michael 2b8b27ef5e ecore_drm2: Add API function to set display DPMS level 2023-03-08 10:42:47 -05:00
Christopher Michael 2ac01d0db7 ecore_drm2: Add API to enable/disable a display 2023-03-08 10:35:07 -05:00
Christopher Michael 0aecba7277 ecore_drm2: Change display_rotation_set to not return a value
As the actual changing of this property will now be 'atomic', we
cannot return a value here until After we try to apply the change so
remove the return type from the function
2023-03-08 10:29:56 -05:00
Christopher Michael 62f8ea49fa ecore_drm2: Add enums for state changes
This patch adds some enums so we can more easily track what has
changed in each objects state. This will allow us to selectively apply
Only what has been changed in each object
2023-03-08 10:26:01 -05:00
Christopher Michael 57caf9a1bb ecore_drm2: Move to using a current & pending state
Large patch that essentially moves all the code to use a current &
pending 'state' so that we can apply changes on vblank
2023-03-08 09:42:33 -05:00
Carsten Haitzler a16e80d8ef theme - new efm perms field - have icon for type if basic file 2023-03-08 09:42:33 -05:00
Carsten Haitzler 7d22469674 elm - icon - policy change. use theme defined std icon FIRST always
if you set a standard named icon - look in the theme first for it as
this should match the look of the theme, THEN look in the selected
icon theme. this fixes blank icons with selecting and icon theme in
many situations and fixes blank cons when "use elm icon theme" is
selected.

@fix
2023-03-08 09:42:33 -05:00
Carsten Haitzler 34c5c1615d eina - debug - fix warning by explicitly casting not auto0-casting
freebsd's new clang wants to make this an error, not a warning... it
should be a warning really... but fix it either way.

@fix
2023-03-08 09:42:33 -05:00
Carsten Haitzler c682ec84cd theme - offer immediate desklock show signal
@feat
2023-03-08 09:42:33 -05:00
NorwayFun 22e9f67abe po: add Georgian 2023-03-08 09:42:33 -05:00
NorwayFun a3e14e6fb8 add Georgian 2023-03-08 09:42:33 -05:00
hugok b6c013a99a Update portuguese translation 2023-03-08 09:42:33 -05:00
Carsten Haitzler 9941a2bdd8 theme - focus glow - no mouse events 2023-03-08 09:42:33 -05:00
Carsten Haitzler e79f4719b5 theme - focus glow - take it off everything 2023-03-08 09:42:33 -05:00
Carsten Haitzler 9204209bc5 theme - new experiment - change zoom + wobble with zooming blue box 2023-03-08 09:42:33 -05:00
Carsten Haitzler b3e3fb12c4 theme experiment - try a window wobble/jiggle when focused
try and highlight focus better with a window wobble to make it easier
to know what is focused. it's fairly small and unobtrusive but a hint
as to what just got focused when alt-tabbing around etc.
2023-03-08 09:42:33 -05:00
Christopher Michael 5929cd7fa9 ecore_drm2: Add API function to return display rotation 2023-01-10 05:42:20 -05:00
Christopher Michael 4a8b57192a ecore_drm2: Ensure display rotation value is filled in during
display_create
2023-01-09 11:45:37 -05:00
Carsten Haitzler 00a44b4169 elm - install elm_widget_item_container_eo.h - fix bug
elm_widget_item_container_eo.h seemingly was not installed. odd. added
to list.

@fix
2023-01-09 11:45:37 -05:00
Carsten Haitzler 3468ca129a elm config tool - fix string mis-use of stale string ptrs from efreet
if efreet updates its in memory db of themes/icons etc. the ptrs you
get from it will be invalid. always dup them out if you keep them
around after going back to main loop control. in this case a tiny
possible leak in stringshare won't ever matter... sot his fixes it

@fix
2023-01-09 11:45:37 -05:00
Christopher Michael f85f6f5ad2 ecore_drm2: Add API to return display info
NB: This is unfinished !! Need to support rotations
2023-01-02 07:56:59 -05:00
Christopher Michael 7b19fbe81c ecore_drm2: Add API to return list of displays 2023-01-02 07:36:23 -05:00
Christopher Michael 5664911df8 ecore_drm2: Add API to get/set if display is primary 2023-01-02 07:28:52 -05:00
Christopher Michael cf2a325012 ecore_drm2: Add API to return display mode info 2023-01-02 07:25:44 -05:00
Christopher Michael 5278c54839 ecore_drm2: Add API to return display modes 2023-01-02 07:22:26 -05:00
Christopher Michael 28e9ef0ec0 ecore_drm2: Add API to return display edid 2023-01-02 07:20:03 -05:00
Christopher Michael f02385bd09 ecore_drm2: Add API to return display crtc id 2023-01-02 06:47:57 -05:00
Christopher Michael b8a257b7d6 ecore_drm2: Add API to return display enabled 2023-01-02 06:42:58 -05:00
Christopher Michael 3a635f0f98 ecore_drm2: Add API function to return dpms value 2022-12-14 06:17:28 -05:00
Christopher Michael 69ecb57c2b ecore_drm2: Add API function to get display physical size 2022-12-13 06:41:48 -05:00
Christopher Michael 5574ab8707 ecore_drm2: Add API function to return display subpixel 2022-12-13 06:39:01 -05:00
Christopher Michael 7ce9125d1e ecore_drm2: Add API function to return connector type 2022-12-13 06:36:44 -05:00
Christopher Michael df5f13ea64 ecore_drm2: Add API to return if a display is connected 2022-12-07 08:21:07 -05:00
Christopher Michael 8f5f7773b3 ecore_drm2: Add API to return if a backlight exists on display 2022-12-07 08:19:06 -05:00
Christopher Michael 122298af42 ecore_drm2: Add API to return display model 2022-12-07 08:10:16 -05:00
Christopher Michael defeaf1313 ecore_drm2: Add API to return display name 2022-12-07 08:08:34 -05:00
Christopher Michael 3d939077ca ecore_drm2: Mark unused parameters
This will change in the future, but for now mark them as unused so we
can shut up the compiler
2022-12-07 07:24:36 -05:00
Christopher Michael e47a812240 ecore_drm2: Add API to get screen size range 2022-12-07 07:19:38 -05:00
Christopher Michael 06960f71ca ecore_drm2: Remove test API
This will get replaced with an actual API
2022-12-07 07:19:33 -05:00
Christopher Michael 92deac89ac ecore_drm2: Add symlinks for libdrm functions needed for Atomic support 2022-12-06 10:35:42 -05:00
Christopher Michael d22f3f389c ecore_drm2: Add support for plane zpos property 2022-12-03 10:12:25 -05:00
Christopher Michael e21afd5d1a ecore_drm2: Cleanup explicit thread handling
There were cases where the thread queue was not being created, and
cases where the thread queue was not being cleaned up properly.
2022-12-03 08:54:42 -05:00
Christopher Michael 01c6609a82 ecore_drm2: Add field to store drm property flags
This will allow us to test if a property is immutable so we do not try
to set a property value on something that cannot be changed. For
example, some drivers have an immutable zpos on planes so we cannot
change those.
2022-12-03 08:02:58 -05:00
Christopher Michael 4504e1d5ee ecore_drm2: Remove dead comments 2022-12-03 07:57:12 -05:00
Christopher Michael 3cd26bcdc2 ecore_drm2: Remove ECORE_DRM2_THREAD_CODE_COMMIT op code
As a portion of the upcoming API will require sending return values
from called functions, we will not use threading for doing atomic
commits so there is no need for this op code.
2022-12-03 06:16:44 -05:00
Christopher Michael cd5afa6128 ecore_drm2: Reorder defines for messages 2022-12-03 06:16:28 -05:00
Christopher Michael 9443dd0adc elementary_config: Fix typo for Entry 'Mangifiers' 2022-12-03 06:16:28 -05:00
Christopher Michael daeb5264a8 evas_main: Minor formatting fixes
NB: No functional changes
2022-12-03 06:16:28 -05:00
Christopher Michael 9d668bd8b4 ecore_drm2: Minor formatting fix 2022-11-15 06:00:38 -05:00
Christopher Michael 0435a37a7e ecore_drm2: Add explicit thread support for drm Planes 2022-11-15 05:47:27 -05:00
Christopher Michael 2948265dc2 ecore_drm2: Add explicit thread support for Displays 2022-11-11 06:26:13 -05:00
Christopher Michael c70d27f7f3 ecore_drm2: Add explicit thread support for drm Connectors 2022-11-08 08:03:34 -05:00
Christopher Michael 1e4761291c ecore_drm2: Fix invalid free, remove useless goto, and don't create
more than one eina_thread_queue
2022-11-08 08:03:27 -05:00
Christopher Michael 3ab68831da ecore_drm2: Switch threading code to use an 'op code'
This should make it easier in the future to add more thread
operations. Also, this fixes up the issue that the eina_thread_queue
was never freed
2022-11-08 07:33:22 -05:00
Christopher Michael b2535043dc ecore_drm2: Add start of explicit threading for crtc state
NB: Pushing this so that the code is up there, but it is certainly
going to change shortly
2022-10-18 10:34:18 -04:00
Christopher Michael ef070b7816 ecore_drm2: Add code to fill Display Modes 2022-09-23 09:16:42 -04:00
Christopher Michael eb4940d94e ecore_drm2: Rename some variables in the structures to avoid confusion
While I hate CamelCase, using drmCrtc, drmConn, etc makes it easier
when reading the code to distinguish what we are operating on/with.
2022-09-22 11:50:52 -04:00
Christopher Michael 1e2517cf07 ecore_drm2: Start on code to add Display Modes 2022-09-20 12:26:45 -04:00
Christopher Michael aa64d0f37c ecore_drm2: Add opaque structure for Ecore_Drm2_Display_Mode 2022-09-20 12:15:09 -04:00
Christopher Michael adb95075fc ecore_drm2: Add backlight support to Displays 2022-09-20 09:36:10 -04:00
Christopher Michael 51ae3a1c9b ecore_drm2: Comment out unused variable in session callback 2022-09-20 09:35:50 -04:00
Christopher Michael 2e01beadd4 ecore_drm2: Remove old ecore_drm2_atomic.c file 2022-09-20 08:44:04 -04:00
Christopher Michael 5dffb60708 ecore_drm2: Add code to fill atomic state in threads for Crtcs, Connectors,
Displays, and Planes
2022-09-20 08:42:55 -04:00
Christopher Michael 2958c10c93 ecore_drm2: Add public structures for Crtc, Connector, Display, Plane
This commit adds opaque API structures for Crtc, Connector, Display,
and Plane. It also adds missing sym_drm functions that we will need
later
2022-09-20 08:42:55 -04:00
Christopher Michael aaa694e551 ecore_drm2: Add API function to get preferred depth 2022-09-20 08:42:55 -04:00
Christopher Michael 94cdf5d9f2 ecore_drm2: Add API function to retrieve cursor size 2022-09-20 08:42:55 -04:00
Christopher Michael 45ef76a41f ecore-drm2: Add code to free Atomic State on device close 2022-09-20 08:42:55 -04:00
Christopher Michael df5a498859 ecore-drm2: Add support to fill Atomic Modesetting state 2022-09-20 08:42:55 -04:00
Christopher Michael 7f24f9793a ecore-drm2: Add symlinks for libdrm functions needed for Atomic support 2022-09-20 08:42:55 -04:00
Christopher Michael e90eab4940 ecore-drm2: Add structures for Atomic Modesetting support 2022-09-20 08:42:55 -04:00
Christopher Michael 275e42275f ecore-drm2: Add enum for rotation 2022-09-20 08:42:55 -04:00
Christopher Michael 75975addc0 ecore-drm2: Be sure to initialize & shutdown elput_input 2022-09-20 08:42:55 -04:00
Christopher Michael 226d306454 ecore-drm2: Add start of Ecore_Drm2_Output structure 2022-09-20 08:42:55 -04:00
Christopher Michael b69bf1a6ac ecore_drm2: Add check for Atomic Modesetting support 2022-09-20 08:42:55 -04:00
Christopher Michael ee17764a5f ecore_drm2: Add code to open & close a drm device 2022-09-20 08:42:55 -04:00
Christopher Michael ea124c0c66 ecore_drm2: Add code to dlopen & symlink needed libdrm functions 2022-09-20 08:42:55 -04:00
Christopher Michael 1e6df64525 ecore_drm2: Start rework of Ecore_Drm2 library
This removes all old code and starts fresh with just simple
ecore_drm2_init & ecore_drm2_shutdown functions
2022-09-20 08:42:55 -04:00
Christopher Michael bcd0ae0b83 efl: Disable building evas drm engine and ecore_evas drm engine
For now we will disable building these as the ecore_drm2 API/ABI is
about to become majorly broken
2022-09-20 08:42:55 -04:00
25 changed files with 2824 additions and 5100 deletions

View File

@ -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";

View File

@ -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;

View File

@ -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;

View File

@ -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

276
po/ka.po Normal file
View File

@ -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 "გაუქმება"

View File

@ -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"

View File

@ -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

View File

@ -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);
}

View File

@ -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;
}
}

View File

@ -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

View File

@ -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;
}

View File

@ -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

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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

View File

@ -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'

View File

@ -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
}

View File

@ -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)
{

View File

@ -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',

View File

@ -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);
}
}

View File

@ -1,6 +1,6 @@
engines = [
['cocoa', ['cocoa']],
['drm', ['drm']],
# ['drm', ['drm']],
['fb', ['fb']],
['sdl', ['sdl']],
['wayland', ['wl']],

View File

@ -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