Date   

[PATCH v2 2/2] dm: vdisplay: multi-vdisplay support.

Sun, Peng
 

From: Sun Peng <peng.p.sun@...>

Allow one VM have more than 1 virtual display for output. Till now, the
max virtual display number is 2. So guest VM can use dual display for
mirror and extend desktop mode. To specify multi-vdisplay, need use
acrn-dm parameters like this:
For fullscreen mode:

virtio-gpu,geometry=fullscreen:monitor_id1,geometry=fullscreen:monitor_id2

For window mode:

virtio-gpu,geometry=<width>x<height>+<x_off>+<y_off>,geometry=<width>x<height>+<x_off>+<y_off>

Signed-off-by: Sun Peng <peng.p.sun@...>
---
devicemodel/hw/vdisplay_sdl.c | 69 +++++++++++++++++++++--------------
1 file changed, 42 insertions(+), 27 deletions(-)

diff --git a/devicemodel/hw/vdisplay_sdl.c b/devicemodel/hw/vdisplay_sdl.c
index e7cabb184..be5ac3a30 100644
--- a/devicemodel/hw/vdisplay_sdl.c
+++ b/devicemodel/hw/vdisplay_sdl.c
@@ -32,7 +32,7 @@
#define VDPY_MIN_WIDTH 640
#define VDPY_MIN_HEIGHT 480
#define transto_10bits(color) (uint16_t)(color * 1024 + 0.5)
-#define VSCREEN_MAX_NUM 1
+#define VSCREEN_MAX_NUM 2

static unsigned char default_raw_argb[VDPY_DEFAULT_WIDTH * VDPY_DEFAULT_HEIGHT * 4];

@@ -1300,7 +1300,7 @@ gfx_ui_deinit()

int vdpy_parse_cmd_option(const char *opts)
{
- char *str;
+ char *str, *stropts, *tmp;
int snum, error;
struct vscreen *vscr;

@@ -1308,35 +1308,50 @@ int vdpy_parse_cmd_option(const char *opts)
vdpy.vscrs = calloc(VSCREEN_MAX_NUM, sizeof(struct vscreen));
vdpy.vscrs_num = 0;

- str = strcasestr(opts, "geometry=");
- vscr = vdpy.vscrs + vdpy.vscrs_num;
- if (opts && strcasestr(opts, "geometry=fullscreen")) {
- snum = sscanf(str, "geometry=fullscreen:%d", &vscr->pscreen_id);
- if (snum != 1) {
+ stropts = strdup(opts);
+ while ((str = strsep(&stropts, ",")) != NULL) {
+ vscr = vdpy.vscrs + vdpy.vscrs_num;
+ tmp = strcasestr(str, "geometry=");
+ if (str && strcasestr(str, "geometry=fullscreen")) {
+ snum = sscanf(tmp, "geometry=fullscreen:%d", &vscr->pscreen_id);
+ if (snum != 1) {
+ vscr->pscreen_id = 0;
+ }
+ vscr->width = VDPY_MAX_WIDTH;
+ vscr->height = VDPY_MAX_HEIGHT;
+ vscr->is_fullscreen = true;
+ pr_info("virtual display: fullscreen on monitor %d.\n",
+ vscr->pscreen_id);
+ vscr->info.xoff = vscr->org_x;
+ vscr->info.yoff = vscr->org_y;
+ vscr->info.width = vscr->width;
+ vscr->info.height = vscr->height;
+ vdpy.vscrs_num++;
+ } else if (str && strcasestr(str, "geometry=")) {
+ snum = sscanf(tmp, "geometry=%dx%d+%d+%d",
+ &vscr->width, &vscr->height,
+ &vscr->org_x, &vscr->org_y);
+ if (snum != 4) {
+ pr_err("incorrect geometry option. Should be"
+ " WxH+x+y\n");
+ error = -1;
+ }
+ vscr->is_fullscreen = false;
vscr->pscreen_id = 0;
+ pr_info("virtual display: windowed on monitor %d.\n",
+ vscr->pscreen_id);
+ vscr->info.xoff = vscr->org_x;
+ vscr->info.yoff = vscr->org_y;
+ vscr->info.width = vscr->width;
+ vscr->info.height = vscr->height;
+ vdpy.vscrs_num++;
}
- vscr->width = VDPY_MAX_WIDTH;
- vscr->height = VDPY_MAX_HEIGHT;
- vscr->is_fullscreen = true;
- vdpy.vscrs_num++;
- pr_info("virtual display: fullscreen.\n");
- } else if (opts && strcasestr(opts, "geometry=")) {
- snum = sscanf(str, "geometry=%dx%d+%d+%d",
- &vscr->width, &vscr->height,
- &vscr->org_x, &vscr->org_y);
- if (snum != 4) {
- pr_err("incorrect geometry option. Should be"
- " WxH+x+y\n");
- error = -1;
+ if (vdpy.vscrs_num > VSCREEN_MAX_NUM) {
+ pr_err("%d virtual displays are too many that acrn-dm can't support!\n");
+ break;
}
- vscr->is_fullscreen = false;
- vdpy.vscrs_num++;
- pr_info("virtual display: windowed.\n");
}
+ free(stropts);

- vscr->info.xoff = 0;
- vscr->info.yoff = 0;
- vscr->info.width = vdpy.vscrs->width;
- vscr->info.height = vdpy.vscrs->height;
return error;
}
--
2.25.1


[PATCH v2 2/2] dm: vdisplay: Add physical monitor id check.

Sun, Peng
 

From: Sun Peng <peng.p.sun@...>

vdisplay use physical monitor id(pscreen index) to locate the monitor.
The max index value always is the physical monitor number - 1. For
example, there are 4 physical monitors connected. The monitor id should
be 0, 1, 2 and 3. We need check monitor id that user inputs and make
sure it is in a correct range.

Signed-off-by: Sun Peng <peng.p.sun@...>
---
devicemodel/hw/vdisplay_sdl.c | 9 +++++++++
1 file changed, 9 insertions(+)

diff --git a/devicemodel/hw/vdisplay_sdl.c b/devicemodel/hw/vdisplay_sdl.c
index 568892e7b..4b0ec69e5 100644
--- a/devicemodel/hw/vdisplay_sdl.c
+++ b/devicemodel/hw/vdisplay_sdl.c
@@ -1147,6 +1147,7 @@ int
gfx_ui_init()
{
SDL_SysWMinfo info;
+ int num_pscreen;

setenv("SDL_VIDEO_X11_FORCE_EGL", "1", 1);
setenv("SDL_OPENGL_ES_DRIVER", "1", 1);
@@ -1158,6 +1159,14 @@ gfx_ui_init()
return -1;
}

+ num_pscreen = SDL_GetNumVideoDisplays();
+ if (vdpy.pscreen_id >= num_pscreen) {
+ pr_err("Monitor id %d is out of avalble range [0~%d].\n",
+ vdpy.pscreen_id, num_pscreen);
+ SDL_Quit();
+ return -1;
+ }
+
SDL_GetDisplayBounds(vdpy.pscreen_id, &vdpy.pscreen_rect);

if (vdpy.pscreen_rect.w < VDPY_MIN_WIDTH ||
--
2.25.1


[PATCH v2 1/2] dm: vdisplay: multi-local-mornitor support.

Sun, Peng
 

From: Sun Peng <peng.p.sun@...>

To support full screen mode on one of multi-local-mornitor which
connected to SOS by monitor ID that customer specify. The monitor ID is
specified in acrn-dm's parameter like this:

virtio-gpu,geometry=fullscreen:monitor_id

For window mode, the vdisplay window always be shown on monitor 0,
because the customer can drag the window to anyone monitor. Besides, the
customer can set the monitor by x_off and y_off parameter like this:

virtio-gpu,geometry=<width>x<height>+<x_off>+<y_off>

Signed-off-by: Sun Peng <peng.p.sun@...>
---
devicemodel/hw/vdisplay_sdl.c | 44 ++++++++++++++++++++++-------------
1 file changed, 28 insertions(+), 16 deletions(-)

diff --git a/devicemodel/hw/vdisplay_sdl.c b/devicemodel/hw/vdisplay_sdl.c
index 65fd78d93..568892e7b 100644
--- a/devicemodel/hw/vdisplay_sdl.c
+++ b/devicemodel/hw/vdisplay_sdl.c
@@ -52,6 +52,8 @@ struct egl_display_ops {
};

static struct display {
+ int pscreen_id;
+ SDL_Rect pscreen_rect;
struct display_info info;
struct state s;
SDL_Texture *dpy_texture;
@@ -62,7 +64,6 @@ static struct display {
int width, height; // Width/height of dpy_win
int org_x, org_y;
int guest_width, guest_height;
- int screen;
struct surface surf;
struct cursor cur;
SDL_Texture *cursor_tex;
@@ -908,17 +909,23 @@ vdpy_sdl_display_thread(void *data)
uint32_t win_flags;
struct vdpy_display_bh *bh;
struct itimerspec ui_timer_spec;
+ int max_width, max_height;
+ int min_width, min_height;

+ max_width = MIN(vdpy.pscreen_rect.w, VDPY_MAX_WIDTH);
+ max_height = MIN(vdpy.pscreen_rect.h, VDPY_MAX_HEIGHT);
+ min_width = MAX(vdpy.pscreen_rect.w, VDPY_MIN_WIDTH);
+ min_height = MAX(vdpy.pscreen_rect.h, VDPY_MIN_HEIGHT);
if (vdpy.width && vdpy.height) {
/* clip the region between (640x480) and (1920x1080) */
- if (vdpy.width < VDPY_MIN_WIDTH)
- vdpy.width = VDPY_MIN_WIDTH;
- if (vdpy.width > VDPY_MAX_WIDTH)
- vdpy.width = VDPY_MAX_WIDTH;
- if (vdpy.height < VDPY_MIN_HEIGHT)
- vdpy.height = VDPY_MIN_HEIGHT;
- if (vdpy.height > VDPY_MAX_HEIGHT)
- vdpy.height = VDPY_MAX_HEIGHT;
+ if (vdpy.width < min_width)
+ vdpy.width = min_width;
+ if (vdpy.width > max_width)
+ vdpy.width = max_width;
+ if (vdpy.height < min_height)
+ vdpy.height = min_height;
+ if (vdpy.height > max_height)
+ vdpy.height = max_height;
} else {
/* the default window(1280x720) is created with undefined pos
* when no geometry info is passed
@@ -933,11 +940,14 @@ vdpy_sdl_display_thread(void *data)
SDL_WINDOW_ALWAYS_ON_TOP |
SDL_WINDOW_SHOWN;
if (vdpy.s.is_fullscreen) {
- win_flags |= SDL_WINDOW_FULLSCREEN;
+ win_flags |= SDL_WINDOW_FULLSCREEN_DESKTOP;
}
vdpy.dpy_win = NULL;
vdpy.dpy_renderer = NULL;
vdpy.dpy_img = NULL;
+ vdpy.org_x = vdpy.pscreen_rect.x;
+ vdpy.org_y = vdpy.pscreen_rect.y;
+ // Zoom to width and height of pscreen is fullscreen enabled
vdpy.dpy_win = SDL_CreateWindow("ACRN_DM",
vdpy.org_x, vdpy.org_y,
vdpy.width, vdpy.height,
@@ -946,6 +956,9 @@ vdpy_sdl_display_thread(void *data)
pr_err("Failed to Create SDL_Window\n");
goto sdl_fail;
}
+ pr_info("SDL display bind to screen %d: [%d,%d,%d,%d].\n", vdpy.pscreen_id,
+ vdpy.org_x, vdpy.org_y, vdpy.width, vdpy.height);
+
vdpy.dpy_renderer = SDL_CreateRenderer(vdpy.dpy_win, -1, 0);
if (vdpy.dpy_renderer == NULL) {
pr_err("Failed to Create GL_Renderer \n");
@@ -1134,7 +1147,6 @@ int
gfx_ui_init()
{
SDL_SysWMinfo info;
- SDL_Rect disp_rect;

setenv("SDL_VIDEO_X11_FORCE_EGL", "1", 1);
setenv("SDL_OPENGL_ES_DRIVER", "1", 1);
@@ -1146,10 +1158,10 @@ gfx_ui_init()
return -1;
}

- SDL_GetDisplayBounds(0, &disp_rect);
+ SDL_GetDisplayBounds(vdpy.pscreen_id, &vdpy.pscreen_rect);

- if (disp_rect.w < VDPY_MIN_WIDTH ||
- disp_rect.h < VDPY_MIN_HEIGHT) {
+ if (vdpy.pscreen_rect.w < VDPY_MIN_WIDTH ||
+ vdpy.pscreen_rect.h < VDPY_MIN_HEIGHT) {
pr_err("Too small resolutions. Please check the "
" graphics system\n");
SDL_Quit();
@@ -1198,9 +1210,9 @@ int vdpy_parse_cmd_option(const char *opts)

str = strcasestr(opts, "geometry=");
if (opts && strcasestr(opts, "geometry=fullscreen")) {
- snum = sscanf(str, "geometry=fullscreen:%d", &vdpy.screen);
+ snum = sscanf(str, "geometry=fullscreen:%d", &vdpy.pscreen_id);
if (snum != 1) {
- vdpy.screen = 0;
+ vdpy.pscreen_id = 0;
}
vdpy.width = VDPY_MAX_WIDTH;
vdpy.height = VDPY_MAX_HEIGHT;
--
2.25.1


Re: [PATCH v2] config_tool-Instruction-missing-for-L2-only-users

Junjie Mao
 

"Junjie Mao" <junjie.mao@...> writes:

Chuang Ke <chuangx.ke@...> writes:

v1-->v2:
1. instruction displayed regardless of if L3 or L2 cache were available, now it displayed instructions accordingly no matter how many caches
2. let instruction displayed only once above the topmost CAT configuration table
From the code changes it seems you want to show the instruction once for
L2 (if there is any L2 cache supporting CAT) AND once for L3 (if there
is any L3 cache supporting CAT). In other words, you'll show the
instruction twice if both L2 and L3 supports CAT. Is that the intended?
Fine with me then.

Reviewed-by: Junjie Mao <junjie.mao@...>


Re: [PATCH v1 1/3] dm: vdisplay: multi-local-mornitor support.

Sun, Peng
 

On Tue, 2022-08-09 at 13:59 +0800, Zhao, Yakui wrote:


On 2022/8/8 13:36, peng.p.sun@... wrote:
From: Sun Peng <peng.p.sun@...>

To support full screen mode on one of multi-local-mornitor which
connected to SOS by monitor ID that customer specify. The monitor
ID is
specified in acrn-dm's parameter like this:

virtio-gpu,geometry=fullscreen:monitor_id

For window mode, the vdisplay window always be shown on monitor 0,
because the customer can drag the window to anyone monitor.
Besides, the
customer can set the monitor by x_off and y_off parameter like
this:

virtio-gpu,geometry=<width>x<height>+<x_off>+<y_off>

Signed-off-by: Sun Peng <peng.p.sun@...>
---
  devicemodel/hw/vdisplay_sdl.c | 43 ++++++++++++++++++++++--------
-----
  1 file changed, 27 insertions(+), 16 deletions(-)

diff --git a/devicemodel/hw/vdisplay_sdl.c
b/devicemodel/hw/vdisplay_sdl.c
index 65fd78d93..7a098f4b2 100644
--- a/devicemodel/hw/vdisplay_sdl.c
+++ b/devicemodel/hw/vdisplay_sdl.c
@@ -52,6 +52,8 @@ struct egl_display_ops {
  };
 
  static struct display {
+       int pscreen_id;
+       SDL_Rect pscreen_rect;
        struct display_info info;
        struct state s;
        SDL_Texture *dpy_texture;
@@ -62,7 +64,6 @@ static struct display {
        int width, height; // Width/height of dpy_win
        int org_x, org_y;
        int guest_width, guest_height;
-       int screen;
        struct surface surf;
        struct cursor cur;
        SDL_Texture *cursor_tex;
@@ -908,17 +909,23 @@ vdpy_sdl_display_thread(void *data)
        uint32_t win_flags;
        struct vdpy_display_bh *bh;
        struct itimerspec ui_timer_spec;
+       int max_width, max_height;
+       int min_width, min_height;
 
+       max_width = MIN(vdpy.pscreen_rect.w, VDPY_MAX_WIDTH);
+       max_height = MIN(vdpy.pscreen_rect.h, VDPY_MAX_HEIGHT);
+       min_width = MAX(vdpy.pscreen_rect.w, VDPY_MIN_WIDTH);
+       min_height = MAX(vdpy.pscreen_rect.h, VDPY_MIN_HEIGHT);
        if (vdpy.width && vdpy.height) {
                /* clip the region between (640x480) and
(1920x1080) */
-               if (vdpy.width < VDPY_MIN_WIDTH)
-                       vdpy.width = VDPY_MIN_WIDTH;
-               if (vdpy.width > VDPY_MAX_WIDTH)
-                       vdpy.width = VDPY_MAX_WIDTH;
-               if (vdpy.height < VDPY_MIN_HEIGHT)
-                       vdpy.height = VDPY_MIN_HEIGHT;
-               if (vdpy.height > VDPY_MAX_HEIGHT)
-                       vdpy.height = VDPY_MAX_HEIGHT;
+               if (vdpy.width < min_width)
+                       vdpy.width = min_width;
+               if (vdpy.width > max_width)
+                       vdpy.width = max_width;
+               if (vdpy.height < min_height)
+                       vdpy.height = min_height;
+               if (vdpy.height > max_height)
+                       vdpy.height = max_height;
        } else {
                /* the default window(1280x720) is created with
undefined pos
                 * when no geometry info is passed
@@ -933,11 +940,13 @@ vdpy_sdl_display_thread(void *data)
                    SDL_WINDOW_ALWAYS_ON_TOP |
                    SDL_WINDOW_SHOWN;
        if (vdpy.s.is_fullscreen) {
-               win_flags |= SDL_WINDOW_FULLSCREEN;
+               win_flags |= SDL_WINDOW_FULLSCREEN_DESKTOP;
        }
What is the difference about the FULLSCREEN/FULLSCREEN_DESKTOP?
Is it really required?
[Sun, Peng]
- SDL_WINDOW_FULLSCREEN, for "real" fullscreen with a videomode change
- SDL_WINDOW_FULLSCREEN_DESKTOP for "fake" fullscreen that takes the
size of the desktop
We should not chage the video mode because this behavior will impect
other VM and get some bad sideffect.

        vdpy.dpy_win = NULL;
        vdpy.dpy_renderer = NULL;
        vdpy.dpy_img = NULL;
+       vdpy.org_x = vdpy.pscreen_rect.x;
+       vdpy.org_y = vdpy.pscreen_rect.y;
        vdpy.dpy_win = SDL_CreateWindow("ACRN_DM",
                                        vdpy.org_x, vdpy.org_y,
                                        vdpy.width, vdpy.height,
@@ -946,6 +955,9 @@ vdpy_sdl_display_thread(void *data)
                pr_err("Failed to Create SDL_Window\n");
                goto sdl_fail;
        }
+       pr_info("SDL display bind to screen %d: [%d,%d,%d,%d].\n",
vdpy.pscreen_id,
+                       vdpy.org_x, vdpy.org_y, vdpy.width,
vdpy.height);
+
        vdpy.dpy_renderer = SDL_CreateRenderer(vdpy.dpy_win, -1,
0);
        if (vdpy.dpy_renderer == NULL) {
                pr_err("Failed to Create GL_Renderer \n");
@@ -1134,7 +1146,6 @@ int
  gfx_ui_init()
  {
        SDL_SysWMinfo info;
-       SDL_Rect disp_rect;
 
        setenv("SDL_VIDEO_X11_FORCE_EGL", "1", 1);
        setenv("SDL_OPENGL_ES_DRIVER", "1", 1);
@@ -1146,10 +1157,10 @@ gfx_ui_init()
                return -1;
        }
 
-       SDL_GetDisplayBounds(0, &disp_rect);
+       SDL_GetDisplayBounds(vdpy.pscreen_id, &vdpy.pscreen_rect);
 
-       if (disp_rect.w < VDPY_MIN_WIDTH ||
-           disp_rect.h < VDPY_MIN_HEIGHT) {
+       if (vdpy.pscreen_rect.w < VDPY_MIN_WIDTH ||
+           vdpy.pscreen_rect.h < VDPY_MIN_HEIGHT) {
                pr_err("Too small resolutions. Please check the "
                       " graphics system\n");
                SDL_Quit();
@@ -1198,9 +1209,9 @@ int vdpy_parse_cmd_option(const char *opts)
 
        str = strcasestr(opts, "geometry=");
        if (opts && strcasestr(opts, "geometry=fullscreen")) {
-               snum = sscanf(str, "geometry=fullscreen:%d",
&vdpy.screen);
+               snum = sscanf(str, "geometry=fullscreen:%d",
&vdpy.pscreen_id);
                if (snum != 1) {
-                       vdpy.screen = 0;
+                       vdpy.pscreen_id = 0;
                }
                vdpy.width = VDPY_MAX_WIDTH;
                vdpy.height = VDPY_MAX_HEIGHT;
--
Sun Peng <peng.p.sun@...>
SSE/ACRN Upstream


Re: [PATCH v2] config_tool-Instruction-missing-for-L2-only-users

Chuang Ke
 

Yes, exactly my intention

Best Regards,
Chuang Ke

-----Original Message-----
From: Mao, Junjie <junjie.mao@...>
Sent: 2022年8月9日 23:22
To: Ke, ChuangX <chuangx.ke@...>
Cc: acrn-dev@...; Xie, Nanlin <nanlin.xie@...>
Subject: Re: [PATCH v2] config_tool-Instruction-missing-for-L2-only-users

Chuang Ke <chuangx.ke@...> writes:

v1-->v2:
1. instruction displayed regardless of if L3 or L2 cache were
available, now it displayed instructions accordingly no matter how
many caches 2. let instruction displayed only once above the topmost
CAT configuration table
From the code changes it seems you want to show the instruction once for
L2 (if there is any L2 cache supporting CAT) AND once for L3 (if there is any L3 cache supporting CAT). In other words, you'll show the instruction twice if both L2 and L3 supports CAT. Is that the intended?

--
Best Regards
Junjie Mao

Signed-off-by: Chuang-Ke <chuangx.ke@...>
Tracked-On: #7921
---
.../pages/Config/ConfigForm/CustomWidget/CAT.vue | 14 +++++++++++---
1 file changed, 11 insertions(+), 3 deletions(-)

diff --git
a/misc/config_tools/configurator/packages/configurator/src/pages/Confi
g/ConfigForm/CustomWidget/CAT.vue
b/misc/config_tools/configurator/packages/configurator/src/pages/Confi
g/ConfigForm/CustomWidget/CAT.vue
index 5a64a3c2f..dcda14ea8 100644
---
a/misc/config_tools/configurator/packages/configurator/src/pages/Confi
g/ConfigForm/CustomWidget/CAT.vue
+++ b/misc/config_tools/configurator/packages/configurator/src/pages/C
+++ onfig/ConfigForm/CustomWidget/CAT.vue
@@ -60,8 +60,8 @@
<div class="py-3" v-if="CAT_INFO.errorMsg">
{{ CAT_INFO.errorMsg }}
</div>
- <div class="py-4" v-for="CACHE_ALLOCATION in CAT_INFO.regions" v-if="RDT_ENABLED==='y'">
- <p v-if="CACHE_ALLOCATION.level===3||CACHE_ALLOCATION.level===2">
+ <div class="py-4" v-for="(CACHE_ALLOCATION,index) in CAT_INFO.regions" v-if="RDT_ENABLED==='y'">
+ <p v-if="showInstruction(CACHE_ALLOCATION.level,index) ">
Drag the ends of the boxes to cover the cache chunks you want to allocate to specific VMs. If you have a
real-time
VM,ensure its cache chunks do not overlap with any other VM's cache chunks.
@@ -218,10 +218,17 @@ export default {
return {
CAT_INFO: {errorMsg: null, regions: [], summary: {}},
SSRAMInfo: this.rootSchema.definitions['SSRAMInfo'],
- RDTType: this.rootSchema.definitions['RDTType']
+ RDTType: this.rootSchema.definitions['RDTType'],
+ InstructionLocation: {},
}
},
methods: {
+ showInstruction(level, index) {
+ if (!(level in this.InstructionLocation)) {
+ this.InstructionLocation[level] = index
+ }
+ return this.InstructionLocation[level]===index
+ },
boardUpdate() {
this.updateCatInfo()
},
@@ -333,6 +340,7 @@ export default {
},
updateCatInfo() {
this.CAT_INFO = configurator.cat.getCATUIData()
+ this.InstructionLocation={}
}
}
}


Re: [PATCH v2] config_tool-Instruction-missing-for-L2-only-users

Junjie Mao
 

Chuang Ke <chuangx.ke@...> writes:

v1-->v2:
1. instruction displayed regardless of if L3 or L2 cache were available, now it displayed instructions accordingly no matter how many caches
2. let instruction displayed only once above the topmost CAT configuration table
From the code changes it seems you want to show the instruction once for
L2 (if there is any L2 cache supporting CAT) AND once for L3 (if there
is any L3 cache supporting CAT). In other words, you'll show the
instruction twice if both L2 and L3 supports CAT. Is that the intended?

--
Best Regards
Junjie Mao

Signed-off-by: Chuang-Ke <chuangx.ke@...>
Tracked-On: #7921
---
.../pages/Config/ConfigForm/CustomWidget/CAT.vue | 14 +++++++++++---
1 file changed, 11 insertions(+), 3 deletions(-)

diff --git a/misc/config_tools/configurator/packages/configurator/src/pages/Config/ConfigForm/CustomWidget/CAT.vue b/misc/config_tools/configurator/packages/configurator/src/pages/Config/ConfigForm/CustomWidget/CAT.vue
index 5a64a3c2f..dcda14ea8 100644
--- a/misc/config_tools/configurator/packages/configurator/src/pages/Config/ConfigForm/CustomWidget/CAT.vue
+++ b/misc/config_tools/configurator/packages/configurator/src/pages/Config/ConfigForm/CustomWidget/CAT.vue
@@ -60,8 +60,8 @@
<div class="py-3" v-if="CAT_INFO.errorMsg">
{{ CAT_INFO.errorMsg }}
</div>
- <div class="py-4" v-for="CACHE_ALLOCATION in CAT_INFO.regions" v-if="RDT_ENABLED==='y'">
- <p v-if="CACHE_ALLOCATION.level===3||CACHE_ALLOCATION.level===2">
+ <div class="py-4" v-for="(CACHE_ALLOCATION,index) in CAT_INFO.regions" v-if="RDT_ENABLED==='y'">
+ <p v-if="showInstruction(CACHE_ALLOCATION.level,index) ">
Drag the ends of the boxes to cover the cache chunks you want to allocate to specific VMs. If you have a
real-time
VM,ensure its cache chunks do not overlap with any other VM's cache chunks.
@@ -218,10 +218,17 @@ export default {
return {
CAT_INFO: {errorMsg: null, regions: [], summary: {}},
SSRAMInfo: this.rootSchema.definitions['SSRAMInfo'],
- RDTType: this.rootSchema.definitions['RDTType']
+ RDTType: this.rootSchema.definitions['RDTType'],
+ InstructionLocation: {},
}
},
methods: {
+ showInstruction(level, index) {
+ if (!(level in this.InstructionLocation)) {
+ this.InstructionLocation[level] = index
+ }
+ return this.InstructionLocation[level]===index
+ },
boardUpdate() {
this.updateCatInfo()
},
@@ -333,6 +340,7 @@ export default {
},
updateCatInfo() {
this.CAT_INFO = configurator.cat.getCATUIData()
+ this.InstructionLocation={}
}
}
}


Re: [PATCH v1 1/3] dm: vdisplay: multi-local-mornitor support.

Zhao, Yakui
 

On 2022/8/8 13:36, peng.p.sun@... wrote:
From: Sun Peng <peng.p.sun@...>
To support full screen mode on one of multi-local-mornitor which
connected to SOS by monitor ID that customer specify. The monitor ID is
specified in acrn-dm's parameter like this:
virtio-gpu,geometry=fullscreen:monitor_id
For window mode, the vdisplay window always be shown on monitor 0,
because the customer can drag the window to anyone monitor. Besides, the
customer can set the monitor by x_off and y_off parameter like this:
virtio-gpu,geometry=<width>x<height>+<x_off>+<y_off>
Signed-off-by: Sun Peng <peng.p.sun@...>
---
devicemodel/hw/vdisplay_sdl.c | 43 ++++++++++++++++++++++-------------
1 file changed, 27 insertions(+), 16 deletions(-)
diff --git a/devicemodel/hw/vdisplay_sdl.c b/devicemodel/hw/vdisplay_sdl.c
index 65fd78d93..7a098f4b2 100644
--- a/devicemodel/hw/vdisplay_sdl.c
+++ b/devicemodel/hw/vdisplay_sdl.c
@@ -52,6 +52,8 @@ struct egl_display_ops {
};
static struct display {
+ int pscreen_id;
+ SDL_Rect pscreen_rect;
struct display_info info;
struct state s;
SDL_Texture *dpy_texture;
@@ -62,7 +64,6 @@ static struct display {
int width, height; // Width/height of dpy_win
int org_x, org_y;
int guest_width, guest_height;
- int screen;
struct surface surf;
struct cursor cur;
SDL_Texture *cursor_tex;
@@ -908,17 +909,23 @@ vdpy_sdl_display_thread(void *data)
uint32_t win_flags;
struct vdpy_display_bh *bh;
struct itimerspec ui_timer_spec;
+ int max_width, max_height;
+ int min_width, min_height;
+ max_width = MIN(vdpy.pscreen_rect.w, VDPY_MAX_WIDTH);
+ max_height = MIN(vdpy.pscreen_rect.h, VDPY_MAX_HEIGHT);
+ min_width = MAX(vdpy.pscreen_rect.w, VDPY_MIN_WIDTH);
+ min_height = MAX(vdpy.pscreen_rect.h, VDPY_MIN_HEIGHT);
if (vdpy.width && vdpy.height) {
/* clip the region between (640x480) and (1920x1080) */
- if (vdpy.width < VDPY_MIN_WIDTH)
- vdpy.width = VDPY_MIN_WIDTH;
- if (vdpy.width > VDPY_MAX_WIDTH)
- vdpy.width = VDPY_MAX_WIDTH;
- if (vdpy.height < VDPY_MIN_HEIGHT)
- vdpy.height = VDPY_MIN_HEIGHT;
- if (vdpy.height > VDPY_MAX_HEIGHT)
- vdpy.height = VDPY_MAX_HEIGHT;
+ if (vdpy.width < min_width)
+ vdpy.width = min_width;
+ if (vdpy.width > max_width)
+ vdpy.width = max_width;
+ if (vdpy.height < min_height)
+ vdpy.height = min_height;
+ if (vdpy.height > max_height)
+ vdpy.height = max_height;
} else {
/* the default window(1280x720) is created with undefined pos
* when no geometry info is passed
@@ -933,11 +940,13 @@ vdpy_sdl_display_thread(void *data)
SDL_WINDOW_ALWAYS_ON_TOP |
SDL_WINDOW_SHOWN;
if (vdpy.s.is_fullscreen) {
- win_flags |= SDL_WINDOW_FULLSCREEN;
+ win_flags |= SDL_WINDOW_FULLSCREEN_DESKTOP;
}
What is the difference about the FULLSCREEN/FULLSCREEN_DESKTOP?
Is it really required?

vdpy.dpy_win = NULL;
vdpy.dpy_renderer = NULL;
vdpy.dpy_img = NULL;
+ vdpy.org_x = vdpy.pscreen_rect.x;
+ vdpy.org_y = vdpy.pscreen_rect.y;
vdpy.dpy_win = SDL_CreateWindow("ACRN_DM",
vdpy.org_x, vdpy.org_y,
vdpy.width, vdpy.height,
@@ -946,6 +955,9 @@ vdpy_sdl_display_thread(void *data)
pr_err("Failed to Create SDL_Window\n");
goto sdl_fail;
}
+ pr_info("SDL display bind to screen %d: [%d,%d,%d,%d].\n", vdpy.pscreen_id,
+ vdpy.org_x, vdpy.org_y, vdpy.width, vdpy.height);
+
vdpy.dpy_renderer = SDL_CreateRenderer(vdpy.dpy_win, -1, 0);
if (vdpy.dpy_renderer == NULL) {
pr_err("Failed to Create GL_Renderer \n");
@@ -1134,7 +1146,6 @@ int
gfx_ui_init()
{
SDL_SysWMinfo info;
- SDL_Rect disp_rect;
setenv("SDL_VIDEO_X11_FORCE_EGL", "1", 1);
setenv("SDL_OPENGL_ES_DRIVER", "1", 1);
@@ -1146,10 +1157,10 @@ gfx_ui_init()
return -1;
}
- SDL_GetDisplayBounds(0, &disp_rect);
+ SDL_GetDisplayBounds(vdpy.pscreen_id, &vdpy.pscreen_rect);
- if (disp_rect.w < VDPY_MIN_WIDTH ||
- disp_rect.h < VDPY_MIN_HEIGHT) {
+ if (vdpy.pscreen_rect.w < VDPY_MIN_WIDTH ||
+ vdpy.pscreen_rect.h < VDPY_MIN_HEIGHT) {
pr_err("Too small resolutions. Please check the "
" graphics system\n");
SDL_Quit();
@@ -1198,9 +1209,9 @@ int vdpy_parse_cmd_option(const char *opts)
str = strcasestr(opts, "geometry=");
if (opts && strcasestr(opts, "geometry=fullscreen")) {
- snum = sscanf(str, "geometry=fullscreen:%d", &vdpy.screen);
+ snum = sscanf(str, "geometry=fullscreen:%d", &vdpy.pscreen_id);
if (snum != 1) {
- vdpy.screen = 0;
+ vdpy.pscreen_id = 0;
}
vdpy.width = VDPY_MAX_WIDTH;
vdpy.height = VDPY_MAX_HEIGHT;


Re: [PATCH v1 1/3] dm: vdisplay: multi-local-mornitor support.

Zhao, Yakui
 

On 2022/8/8 13:36, peng.p.sun@... wrote:
From: Sun Peng <peng.p.sun@...>
To support full screen mode on one of multi-local-mornitor which
connected to SOS by monitor ID that customer specify. The monitor ID is
specified in acrn-dm's parameter like this:
It seems that this patch mainly handles the issue of multi monitors.
It will be better that this is submitted as the separate patch set.
virtio-gpu,geometry=fullscreen:monitor_id
For window mode, the vdisplay window always be shown on monitor 0,
because the customer can drag the window to anyone monitor. Besides, the
customer can set the monitor by x_off and y_off parameter like this:
virtio-gpu,geometry=<width>x<height>+<x_off>+<y_off>
Signed-off-by: Sun Peng <peng.p.sun@...>
---
devicemodel/hw/vdisplay_sdl.c | 43 ++++++++++++++++++++++-------------
1 file changed, 27 insertions(+), 16 deletions(-)
diff --git a/devicemodel/hw/vdisplay_sdl.c b/devicemodel/hw/vdisplay_sdl.c
index 65fd78d93..7a098f4b2 100644
--- a/devicemodel/hw/vdisplay_sdl.c
+++ b/devicemodel/hw/vdisplay_sdl.c
@@ -52,6 +52,8 @@ struct egl_display_ops {
};
static struct display {
+ int pscreen_id;
+ SDL_Rect pscreen_rect;
struct display_info info;
struct state s;
SDL_Texture *dpy_texture;
@@ -62,7 +64,6 @@ static struct display {
int width, height; // Width/height of dpy_win
int org_x, org_y;
int guest_width, guest_height;
- int screen;
struct surface surf;
struct cursor cur;
SDL_Texture *cursor_tex;
@@ -908,17 +909,23 @@ vdpy_sdl_display_thread(void *data)
uint32_t win_flags;
struct vdpy_display_bh *bh;
struct itimerspec ui_timer_spec;
+ int max_width, max_height;
+ int min_width, min_height;
+ max_width = MIN(vdpy.pscreen_rect.w, VDPY_MAX_WIDTH);
+ max_height = MIN(vdpy.pscreen_rect.h, VDPY_MAX_HEIGHT);
+ min_width = MAX(vdpy.pscreen_rect.w, VDPY_MIN_WIDTH);
+ min_height = MAX(vdpy.pscreen_rect.h, VDPY_MIN_HEIGHT);
if (vdpy.width && vdpy.height) {
/* clip the region between (640x480) and (1920x1080) */
- if (vdpy.width < VDPY_MIN_WIDTH)
- vdpy.width = VDPY_MIN_WIDTH;
- if (vdpy.width > VDPY_MAX_WIDTH)
- vdpy.width = VDPY_MAX_WIDTH;
- if (vdpy.height < VDPY_MIN_HEIGHT)
- vdpy.height = VDPY_MIN_HEIGHT;
- if (vdpy.height > VDPY_MAX_HEIGHT)
- vdpy.height = VDPY_MAX_HEIGHT;
+ if (vdpy.width < min_width)
+ vdpy.width = min_width;
+ if (vdpy.width > max_width)
+ vdpy.width = max_width;
+ if (vdpy.height < min_height)
+ vdpy.height = min_height;
+ if (vdpy.height > max_height)
+ vdpy.height = max_height;
} else {
/* the default window(1280x720) is created with undefined pos
* when no geometry info is passed
@@ -933,11 +940,13 @@ vdpy_sdl_display_thread(void *data)
SDL_WINDOW_ALWAYS_ON_TOP |
SDL_WINDOW_SHOWN;
if (vdpy.s.is_fullscreen) {
- win_flags |= SDL_WINDOW_FULLSCREEN;
+ win_flags |= SDL_WINDOW_FULLSCREEN_DESKTOP;
}
vdpy.dpy_win = NULL;
vdpy.dpy_renderer = NULL;
vdpy.dpy_img = NULL;
+ vdpy.org_x = vdpy.pscreen_rect.x;
+ vdpy.org_y = vdpy.pscreen_rect.y;
vdpy.dpy_win = SDL_CreateWindow("ACRN_DM",
vdpy.org_x, vdpy.org_y,
vdpy.width, vdpy.height,
The vdpy.width/height is clipped if the region of phys monitor is 3840x2160.

Can we add different definitions to describe the width/height for guest?

@@ -946,6 +955,9 @@ vdpy_sdl_display_thread(void *data)
pr_err("Failed to Create SDL_Window\n");
goto sdl_fail;
}
+ pr_info("SDL display bind to screen %d: [%d,%d,%d,%d].\n", vdpy.pscreen_id,
+ vdpy.org_x, vdpy.org_y, vdpy.width, vdpy.height);
+
vdpy.dpy_renderer = SDL_CreateRenderer(vdpy.dpy_win, -1, 0);
if (vdpy.dpy_renderer == NULL) {
pr_err("Failed to Create GL_Renderer \n");
@@ -1134,7 +1146,6 @@ int
gfx_ui_init()
{
SDL_SysWMinfo info;
- SDL_Rect disp_rect;
setenv("SDL_VIDEO_X11_FORCE_EGL", "1", 1);
setenv("SDL_OPENGL_ES_DRIVER", "1", 1);
@@ -1146,10 +1157,10 @@ gfx_ui_init()
return -1;
}
- SDL_GetDisplayBounds(0, &disp_rect);
+ SDL_GetDisplayBounds(vdpy.pscreen_id, &vdpy.pscreen_rect);
- if (disp_rect.w < VDPY_MIN_WIDTH ||
- disp_rect.h < VDPY_MIN_HEIGHT) {
+ if (vdpy.pscreen_rect.w < VDPY_MIN_WIDTH ||
+ vdpy.pscreen_rect.h < VDPY_MIN_HEIGHT) {
pr_err("Too small resolutions. Please check the "
" graphics system\n");
SDL_Quit();
@@ -1198,9 +1209,9 @@ int vdpy_parse_cmd_option(const char *opts)
str = strcasestr(opts, "geometry=");
if (opts && strcasestr(opts, "geometry=fullscreen")) {
- snum = sscanf(str, "geometry=fullscreen:%d", &vdpy.screen);
+ snum = sscanf(str, "geometry=fullscreen:%d", &vdpy.pscreen_id);
if (snum != 1) {
- vdpy.screen = 0;
+ vdpy.pscreen_id = 0;
}
It will be better to add another patch that will check whether the input pscreen_id is valid.

vdpy.width = VDPY_MAX_WIDTH;
vdpy.height = VDPY_MAX_HEIGHT;


Re: [PATCH] dm: bugfix for iothread

Conghui Chen
 

-----Original Message-----
From: Zhao, Yakui <yakui.zhao@...>
Sent: Tuesday, August 9, 2022 1:51 PM
To: acrn-dev@...
Cc: Wang, Yu1 <yu1.wang@...>; Chen, Conghui
<conghui.chen@...>
Subject: Re: [acrn-dev] [PATCH] dm: bugfix for iothread



On 2022/8/9 12:29, Conghui Chen wrote:
As the type of pthread_t is unsigned long, so the init value for it
should not be '-1', change it to 0.
It will be better to describe the issue.
For example: if the tid is -1, it will continue to call
pthread_kill/pthread_join. This is incorrect.
Thanks for your comment, will change the commit message.

Regards,
Conghui.


LGTM except minor commit log.

Add: Reviewed-by: Zhao Yakui <yakui.zhao@...>

Signed-off-by: Conghui <conghui.chen@...>
---
devicemodel/core/iothread.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/devicemodel/core/iothread.c b/devicemodel/core/iothread.c
index 0f56ea60d..238ecb375 100644
--- a/devicemodel/core/iothread.c
+++ b/devicemodel/core/iothread.c
@@ -145,7 +145,7 @@ iothread_init(void)
pthread_mutex_init(&ioctx.mtx, &attr);
pthread_mutexattr_destroy(&attr);

- ioctx.tid = -1;
+ ioctx.tid = 0;
ioctx.started = false;
ioctx.epfd = epoll_create1(0);


Re: [PATCH] dm: bugfix for iothread

Zhao, Yakui
 

On 2022/8/9 12:29, Conghui Chen wrote:
As the type of pthread_t is unsigned long, so the init value for it
should not be '-1', change it to 0.
It will be better to describe the issue.
For example: if the tid is -1, it will continue to call pthread_kill/pthread_join. This is incorrect.

LGTM except minor commit log.

Add: Reviewed-by: Zhao Yakui <yakui.zhao@...>

Signed-off-by: Conghui <conghui.chen@...>
---
devicemodel/core/iothread.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/devicemodel/core/iothread.c b/devicemodel/core/iothread.c
index 0f56ea60d..238ecb375 100644
--- a/devicemodel/core/iothread.c
+++ b/devicemodel/core/iothread.c
@@ -145,7 +145,7 @@ iothread_init(void)
pthread_mutex_init(&ioctx.mtx, &attr);
pthread_mutexattr_destroy(&attr);
- ioctx.tid = -1;
+ ioctx.tid = 0;
ioctx.started = false;
ioctx.epfd = epoll_create1(0);


[PATCH] dm: bugfix for iothread

Conghui Chen
 

As the type of pthread_t is unsigned long, so the init value for it
should not be '-1', change it to 0.

Signed-off-by: Conghui <conghui.chen@...>
---
devicemodel/core/iothread.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/devicemodel/core/iothread.c b/devicemodel/core/iothread.c
index 0f56ea60d..238ecb375 100644
--- a/devicemodel/core/iothread.c
+++ b/devicemodel/core/iothread.c
@@ -145,7 +145,7 @@ iothread_init(void)
pthread_mutex_init(&ioctx.mtx, &attr);
pthread_mutexattr_destroy(&attr);

- ioctx.tid = -1;
+ ioctx.tid = 0;
ioctx.started = false;
ioctx.epfd = epoll_create1(0);

--
2.25.1


Re: [PATCH v1 3/3] dm: vdisplay: multi-vdisplay support.

Sun, Peng
 

On Mon, 2022-08-08 at 16:52 +0800, Zhao, Yakui wrote:


On 2022/8/8 13:36, peng.p.sun@... wrote:
From: Sun Peng <peng.p.sun@...>

Allow one VM have more than 1 virtual display for output. Till now,
the
max virtual display number is 2. So guest VM can use dual display
for
mirror and extend desktop mode. To specify multi-vdisplay, need use
acrn-dm parameters like this:
For fullscreen mode:
After multi vscreens are supported, it will be better that the error
message is printed with the vscr_id.
Otherwise it is difficult to check where is the problem.
[Sun, Peng] vscr_id will be printed in next version.


virtio-
gpu,geometry=fullscreen:monitor_id1,geometry=fullscreen:monitor_id2

For window mode:

virtio-
gpu,geometry=<width>x<height>+<x_off>+<y_off>,geometry=<width>x<hei
ght>+<x_off>+<y_off>

Signed-off-by: Sun Peng <peng.p.sun@...>
---
  devicemodel/hw/vdisplay_sdl.c | 67 +++++++++++++++++++++---------
-----
  1 file changed, 40 insertions(+), 27 deletions(-)

diff --git a/devicemodel/hw/vdisplay_sdl.c
b/devicemodel/hw/vdisplay_sdl.c
index 28457c52e..c7a279ab6 100644
--- a/devicemodel/hw/vdisplay_sdl.c
+++ b/devicemodel/hw/vdisplay_sdl.c
@@ -32,7 +32,7 @@
  #define VDPY_MIN_WIDTH 640
  #define VDPY_MIN_HEIGHT 480
  #define transto_10bits(color) (uint16_t)(color * 1024 + 0.5)
-#define VSCREEN_MAX_NUM 1
+#define VSCREEN_MAX_NUM 2
 
  static unsigned char default_raw_argb[VDPY_DEFAULT_WIDTH *
VDPY_DEFAULT_HEIGHT * 4];
 
@@ -1323,7 +1323,7 @@ gfx_ui_deinit()
 
  int vdpy_parse_cmd_option(const char *opts)
  {
-       char *str;
+       char *str, *stropts, *tmp;
        int snum, error;
        struct vscreen *vscr;
 
@@ -1331,35 +1331,48 @@ int vdpy_parse_cmd_option(const char *opts)
        vdpy.vscrs = calloc(VSCREEN_MAX_NUM, sizeof(struct
vscreen));
        vdpy.vscrs_num = 0;
 
-       str = strcasestr(opts, "geometry=");
-       vscr = vdpy.vscrs + vdpy.vscrs_num;
-       if (opts && strcasestr(opts, "geometry=fullscreen")) {
-               snum = sscanf(str, "geometry=fullscreen:%d", &vscr-
pscreen_id);
-               if (snum != 1) {
+       stropts = strdup(opts);
+       while ((str = strsep(&stropts, ",")) != NULL) {
+               vscr = vdpy.vscrs + vdpy.vscrs_num;
+               tmp = strcasestr(str, "geometry=");
+               if (str && strcasestr(str, "geometry=fullscreen"))
{
+                       snum = sscanf(tmp,
"geometry=fullscreen:%d", &vscr->pscreen_id);
+                       if (snum != 1) {
+                               vscr->pscreen_id = 0;
+                       }
+                       vscr->width = VDPY_MAX_WIDTH;
+                       vscr->height = VDPY_MAX_HEIGHT;
+                       vscr->is_fullscreen = true;
+                       pr_info("virtual display: fullscreen.\n");
+                       vscr->info.xoff = vscr->org_x;
+                       vscr->info.yoff = vscr->org_y;
+                       vscr->info.width = vscr->width;
+                       vscr->info.height = vscr->height;
+                       vdpy.vscrs_num++;
+               } else if (str && strcasestr(str, "geometry=")) {
+                       snum = sscanf(tmp, "geometry=%dx%d+%d+%d",
+                                       &vscr->width, &vscr-
height,
+                                       &vscr->org_x, &vscr-
org_y);
+                       if (snum != 4) {
+                               pr_err("incorrect geometry option.
Should be"
+                                               " WxH+x+y\n");
+                               error = -1;
+                       }
+                       vscr->is_fullscreen = false;
                        vscr->pscreen_id = 0;
+                       pr_info("virtual display: windowed.\n");
+                       vscr->info.xoff = vscr->org_x;
+                       vscr->info.yoff = vscr->org_y;
+                       vscr->info.width = vscr->width;
+                       vscr->info.height = vscr->height;
+                       vdpy.vscrs_num++;
                }
-               vscr->width = VDPY_MAX_WIDTH;
-               vscr->height = VDPY_MAX_HEIGHT;
-               vscr->is_fullscreen = true;
-               vdpy.vscrs_num++;
-               pr_info("virtual display: fullscreen.\n");
-       } else if (opts && strcasestr(opts, "geometry=")) {
-               snum = sscanf(str, "geometry=%dx%d+%d+%d",
-                               &vscr->width, &vscr->height,
-                               &vscr->org_x, &vscr->org_y);
-               if (snum != 4) {
-                       pr_err("incorrect geometry option. Should
be"
-                                       " WxH+x+y\n");
-                       error = -1;
+               if (vdpy.vscrs_num > VSCREEN_MAX_NUM) {
+                       pr_err("Too many virtual display that acrn-
dm can't support!\n");
+                       break;
                }
-               vscr->is_fullscreen = false;
-               vdpy.vscrs_num++;
-               pr_info("virtual display: windowed.\n");
        }
+       free(stropts);
 
-       vscr->info.xoff = 0;
-       vscr->info.yoff = 0;
-       vscr->info.width = vdpy.vscrs->width;
-       vscr->info.height = vdpy.vscrs->height;
        return error;
  }
--
Sun Peng <peng.p.sun@...>
SSE/ACRN Upstream


Re: [PATCH v1 2/3] dm: vdisplay: refine vdisplay core concept abstractions

Sun, Peng
 

On Mon, 2022-08-08 at 16:42 +0800, Zhao, Yakui wrote:


On 2022/8/8 13:36, peng.p.sun@... wrote:
From: Sun Peng <peng.p.sun@...>

Add new concept "vscreen" to abstract all specs about screen in a
display server. This can provide convenience to add more screens
for one VM.

Signed-off-by: Sun Peng <peng.p.sun@...>
---
  devicemodel/hw/vdisplay_sdl.c | 503 +++++++++++++++++++++--------
-----
  1 file changed, 315 insertions(+), 188 deletions(-)

diff --git a/devicemodel/hw/vdisplay_sdl.c
b/devicemodel/hw/vdisplay_sdl.c
index 7a098f4b2..28457c52e 100644
--- a/devicemodel/hw/vdisplay_sdl.c
+++ b/devicemodel/hw/vdisplay_sdl.c
@@ -32,6 +32,7 @@
  #define VDPY_MIN_WIDTH 640
  #define VDPY_MIN_HEIGHT 480
  #define transto_10bits(color) (uint16_t)(color * 1024 + 0.5)
+#define VSCREEN_MAX_NUM 1
 
  static unsigned char default_raw_argb[VDPY_DEFAULT_WIDTH *
VDPY_DEFAULT_HEIGHT * 4];
 
@@ -40,8 +41,6 @@ struct state {
        bool is_active;
        bool is_wayland;
        bool is_x11;
-       bool is_fullscreen;
-       uint64_t updates;
        int n_connect;
  };
 
@@ -51,27 +50,39 @@ struct egl_display_ops {
        PFNGLEGLIMAGETARGETTEXTURE2DOESPROC
glEGLImageTargetTexture2DOES;
  };
 
-static struct display {
+struct vscreen {
+       struct display_info info;
        int pscreen_id;
        SDL_Rect pscreen_rect;
-       struct display_info info;
-       struct state s;
-       SDL_Texture *dpy_texture;
-       SDL_Window *dpy_win;
-       SDL_Renderer *dpy_renderer;
-       pixman_image_t *dpy_img;
-       pthread_t tid;
-       int width, height; // Width/height of dpy_win
-       int org_x, org_y;
-       int guest_width, guest_height;
+       bool is_fullscreen;
+       int org_x;
+       int org_y;
+       int width;
+       int height;
+       int guest_width;
+       int guest_height;
        struct surface surf;
        struct cursor cur;
-       SDL_Texture *cursor_tex;
+       SDL_Texture *surf_tex;
+       SDL_Texture *cur_tex;
+       int surf_updates;
+       int cur_updates;
+       SDL_Window *win;
+       SDL_Renderer *renderer;
+       pixman_image_t *img;
+       EGLImage egl_img;
+       /* Record the update_time that is activated from guest_vm
*/
+       struct timespec last_time;
+};
+
+static struct display {
+       struct state s;
+       struct vscreen *vscrs;
+       int vscrs_num;
+       pthread_t tid;
        /* Add one UI_timer(33ms) to render the buffers from
guest_vm */
        struct acrn_timer ui_timer;
        struct vdpy_display_bh ui_timer_bh;
-       /* Record the update_time that is activated from guest_vm
*/
-       struct timespec last_time;
        // protect the request_list
        pthread_mutex_t vdisplay_mutex;
        // receive the signal that request is submitted
@@ -82,14 +93,11 @@ static struct display {
        SDL_GLContext eglContext;
        EGLDisplay eglDisplay;
        struct egl_display_ops gl_ops;
-       EGLImage cur_egl_img;
  } vdpy = {
        .s.is_ui_realized = false,
        .s.is_active = false,
        .s.is_wayland = false,
        .s.is_x11 = false,
-       .s.is_fullscreen = false,
-       .s.updates = 0,
        .s.n_connect = 0
  };
 
@@ -514,10 +522,19 @@ void
  vdpy_get_edid(int handle, int scanout_id, uint8_t *edid, size_t
size)
  {
        struct edid_info edid_info;
+       struct vscreen *vscr;
+
+       if (scanout_id >= vdpy.vscrs_num)
+               return;
+
+       vscr = vdpy.vscrs + scanout_id;
+       if (vscr == NULL) {
+               return;
+       }
 
        if (handle == vdpy.s.n_connect) {
-               edid_info.prefx = vdpy.info.width;
-               edid_info.prefy = vdpy.info.height;
+               edid_info.prefx = vscr->info.width;
+               edid_info.prefy = vscr->info.height;
                edid_info.maxx = VDPY_MAX_WIDTH;
                edid_info.maxy = VDPY_MAX_HEIGHT;
        } else {
@@ -537,11 +554,21 @@ vdpy_get_edid(int handle, int scanout_id,
uint8_t *edid, size_t size)
  void
  vdpy_get_display_info(int handle, int scanout_id, struct
display_info *info)
  {
+       struct vscreen *vscr;
+
+       if (scanout_id >= vdpy.vscrs_num)
+               return;
+
+       vscr = vdpy.vscrs + scanout_id;
+       if (vscr == NULL) {
+               return;
+       }
+
        if (handle == vdpy.s.n_connect) {
-               info->xoff = vdpy.info.xoff;
-               info->yoff = vdpy.info.yoff;
-               info->width = vdpy.info.width;
-               info->height = vdpy.info.height;
+               info->xoff = vscr->info.xoff;
+               info->yoff = vscr->info.yoff;
+               info->width = vscr->info.width;
+               info->height = vscr->info.height;
        } else {
                info->xoff = 0;
                info->yoff = 0;
@@ -554,6 +581,8 @@ static void
  sdl_gl_display_init(void)
  {
        struct egl_display_ops *gl_ops = &vdpy.gl_ops;
+       struct vscreen *vscr;
+       int i;
 
        /* obtain the eglDisplay/eglContext */
        vdpy.eglDisplay = eglGetCurrentDisplay();
@@ -570,7 +599,15 @@ sdl_gl_display_init(void)
        gl_ops->glEGLImageTargetTexture2DOES =
(PFNGLEGLIMAGETARGETTEXTURE2DOESPROC)
                                eglGetProcAddress("glEGLImageTarget
Texture2DOES");
 
-       vdpy.cur_egl_img = EGL_NO_IMAGE_KHR;
+       for (i = 0; i < vdpy.vscrs_num; i++) {
+               vscr = vdpy.vscrs + i;
+               if (vscr == NULL) {
+                       continue;
+               }
+
+               vscr->egl_img = EGL_NO_IMAGE_KHR;
+       }
+
        if ((gl_ops->eglCreateImageKHR == NULL) ||
                (gl_ops->eglDestroyImageKHR == NULL) ||
                (gl_ops->glEGLImageTargetTexture2DOES == NULL)) {
@@ -588,6 +625,7 @@ vdpy_surface_set(int handle, int scanout_id,
struct surface *surf)
        pixman_image_t *src_img;
        int format;
        int access, i;
+       struct vscreen *vscr;
 
        if (handle != vdpy.s.n_connect) {
                return;
@@ -599,9 +637,18 @@ vdpy_surface_set(int handle, int scanout_id,
struct surface *surf)
                return;
        }
 
+       if (scanout_id >= vdpy.vscrs_num) {
+               return;
+       }
+
+       vscr = vdpy.vscrs + scanout_id;
+       if (vscr == NULL) {
+               return;
+       }
+
        if (surf == NULL ) {
-               vdpy.surf.width = 0;
-               vdpy.surf.height = 0;
+               vscr->surf.width = 0;
+               vscr->surf.height = 0;
                /* Need to use the default 640x480 for the
SDL_Texture */
                src_img = pixman_image_create_bits(PIXMAN_a8r8g8b8,
                        VDPY_MIN_WIDTH, VDPY_MIN_HEIGHT,
@@ -611,8 +658,8 @@ vdpy_surface_set(int handle, int scanout_id,
struct surface *surf)
                        pr_err("failed to create pixman_image\n");
                        return;
                }
-               vdpy.guest_width = VDPY_MIN_WIDTH;
-               vdpy.guest_height = VDPY_MIN_HEIGHT;
+               vscr->guest_width = VDPY_MIN_WIDTH;
+               vscr->guest_height = VDPY_MIN_HEIGHT;
        } else if (surf->surf_type == SURFACE_PIXMAN) {
                src_img = pixman_image_create_bits(surf-
surf_format,
                        surf->width, surf->height, surf->pixel,
@@ -621,21 +668,21 @@ vdpy_surface_set(int handle, int scanout_id,
struct surface *surf)
                        pr_err("failed to create pixman_image\n");
                        return;
                }
-               vdpy.surf = *surf;
-               vdpy.guest_width = surf->width;
-               vdpy.guest_height = surf->height;
+               vscr->surf = *surf;
+               vscr->guest_width = surf->width;
+               vscr->guest_height = surf->height;
        } else if (surf->surf_type == SURFACE_DMABUF) {
                src_img = NULL;
-               vdpy.surf = *surf;
-               vdpy.guest_width = surf->width;
-               vdpy.guest_height = surf->height;
+               vscr->surf = *surf;
+               vscr->guest_width = surf->width;
+               vscr->guest_height = surf->height;
        } else {
                /* Unsupported type */
                return;
        }
 
-       if (vdpy.dpy_texture) {
-               SDL_DestroyTexture(vdpy.dpy_texture);
+       if (vscr->surf_tex) {
+               SDL_DestroyTexture(vscr->surf_tex);
        }
        if (surf && (surf->surf_type == SURFACE_DMABUF)) {
                access = SDL_TEXTUREACCESS_STATIC;
@@ -666,23 +713,23 @@ vdpy_surface_set(int handle, int scanout_id,
struct surface *surf)
                                        pixman_image_get_format(src
_img));
                }
        }
-       vdpy.dpy_texture = SDL_CreateTexture(vdpy.dpy_renderer,
+       vscr->surf_tex = SDL_CreateTexture(vscr->renderer,
                        format, access,
-                       vdpy.guest_width, vdpy.guest_height);
+                       vscr->guest_width, vscr->guest_height);
 
-       if (vdpy.dpy_texture == NULL) {
+       if (vscr->surf_tex == NULL) {
                pr_err("Failed to create SDL_texture for
surface.\n");
        }
 
        /* For the surf_switch, it will be updated in
surface_update */
        if (!surf) {
-               SDL_UpdateTexture(vdpy.dpy_texture, NULL,
+               SDL_UpdateTexture(vscr->surf_tex, NULL,
                                  pixman_image_get_data(src_img),
                                 
pixman_image_get_stride(src_img));
 
-               SDL_RenderClear(vdpy.dpy_renderer);
-               SDL_RenderCopy(vdpy.dpy_renderer, vdpy.dpy_texture,
NULL, NULL);
-               SDL_RenderPresent(vdpy.dpy_renderer);
+               SDL_RenderClear(vscr->renderer);
+               SDL_RenderCopy(vscr->renderer, vscr->surf_tex,
NULL, NULL);
+               SDL_RenderPresent(vscr->renderer);
        } else if (surf->surf_type == SURFACE_DMABUF) {
                EGLImageKHR egl_img = EGL_NO_IMAGE_KHR;
                EGLint attrs[64];
@@ -713,46 +760,58 @@ vdpy_surface_set(int handle, int scanout_id,
struct surface *surf)
                        return;
                }
 
-               SDL_GL_BindTexture(vdpy.dpy_texture, NULL, NULL);
+               SDL_GL_BindTexture(vscr->surf_tex, NULL, NULL);
                gl_ops-
glEGLImageTargetTexture2DOES(GL_TEXTURE_EXTERNAL_OES, egl_img);
-               if (vdpy.cur_egl_img != EGL_NO_IMAGE_KHR)
+               if (vscr->egl_img != EGL_NO_IMAGE_KHR)
                        gl_ops->eglDestroyImageKHR(vdpy.eglDisplay,
-                                       vdpy.cur_egl_img);
+                                       vscr->egl_img);
 
                /* In theory the created egl_img can be released
after it is bound
                 * to texture.
                 * Now it is released next time so that it is
controlled correctly
                 */
-               vdpy.cur_egl_img = egl_img;
+               vscr->egl_img = egl_img;
        }
 
-       if (vdpy.dpy_img)
-               pixman_image_unref(vdpy.dpy_img);
+       if (vscr->img)
+               pixman_image_unref(vscr->img);
 
        if (surf == NULL) {
-               SDL_SetWindowTitle(vdpy.dpy_win,
+               SDL_SetWindowTitle(vscr->win,
                                "Not activate display yet!");
        } else {
-               SDL_SetWindowTitle(vdpy.dpy_win,
+               SDL_SetWindowTitle(vscr->win,
                                "ACRN Virtual Monitor");
        }
        /* Replace the cur_img with the created_img */
-       vdpy.dpy_img = src_img;
+       vscr->img = src_img;
  }
 
  void
-vdpy_cursor_position_transformation(struct display *vdpy, SDL_Rect
*rect)
+vdpy_cursor_position_transformation(struct display *vdpy, int
scanout_id, SDL_Rect *rect)
  {
-       rect->x = (vdpy->cur.x * vdpy->width) / vdpy->guest_width;
-       rect->y = (vdpy->cur.y * vdpy->height) / vdpy-
guest_height;
-       rect->w = (vdpy->cur.width * vdpy->width) / vdpy-
guest_width;
-       rect->h = (vdpy->cur.height * vdpy->height) / vdpy-
guest_height;
+       struct vscreen *vscr;
+
+       if (scanout_id >= vdpy->vscrs_num) {
+               return;
+       }
+
+       vscr = vdpy->vscrs + scanout_id;
+       if(vscr == NULL) {
+               return;
+       }
+
+       rect->x = (vscr->cur.x * vscr->width) / vscr->guest_width;
+       rect->y = (vscr->cur.y * vscr->height) / vscr-
guest_height;
+       rect->w = (vscr->cur.width * vscr->width) / vscr-
guest_width;
+       rect->h = (vscr->cur.height * vscr->height) / vscr-
guest_height;
  }
 
  void
  vdpy_surface_update(int handle, int scanout_id, struct surface
*surf)
  {
        SDL_Rect cursor_rect;
+       struct vscreen *vscr;
 
        if (handle != vdpy.s.n_connect) {
                return;
@@ -769,32 +828,43 @@ vdpy_surface_update(int handle, int
scanout_id, struct surface *surf)
                return;
        }
 
+       if (scanout_id >= vdpy.vscrs_num) {
+               return;
+       }
+
+       vscr = vdpy.vscrs + scanout_id;
+       if (vscr == NULL) {
+               return;
+       }
+
        if (surf->surf_type == SURFACE_PIXMAN)
-               SDL_UpdateTexture(vdpy.dpy_texture, NULL,
+               SDL_UpdateTexture(vscr->surf_tex, NULL,
                          surf->pixel,
                          surf->stride);
 
-       SDL_RenderClear(vdpy.dpy_renderer);
-       SDL_RenderCopy(vdpy.dpy_renderer, vdpy.dpy_texture, NULL,
NULL);
+       SDL_RenderClear(vscr->renderer);
+       SDL_RenderCopy(vscr->renderer, vscr->surf_tex, NULL, NULL);
 
        /* This should be handled after rendering the
surface_texture.
         * Otherwise it will be hidden
         */
-       if (vdpy.cursor_tex) {
-               vdpy_cursor_position_transformation(&vdpy,
&cursor_rect);
-               SDL_RenderCopy(vdpy.dpy_renderer, vdpy.cursor_tex,
+       if (vscr->cur_tex) {
+               vdpy_cursor_position_transformation(&vdpy,
scanout_id, &cursor_rect);
+               SDL_RenderCopy(vscr->renderer, vscr->cur_tex,
                                NULL, &cursor_rect);
        }
 
-       SDL_RenderPresent(vdpy.dpy_renderer);
+       SDL_RenderPresent(vscr->renderer);
 
        /* update the rendering time */
-       clock_gettime(CLOCK_MONOTONIC, &vdpy.last_time);
+       clock_gettime(CLOCK_MONOTONIC, &vscr->last_time);
  }
 
  void
  vdpy_cursor_define(int handle, int scanout_id, struct cursor
*cur)
  {
+       struct vscreen *vscr;
+
        if (handle != vdpy.s.n_connect) {
                return;
        }
@@ -805,39 +875,55 @@ vdpy_cursor_define(int handle, int
scanout_id, struct cursor *cur)
                return;
        }
 
+       if (scanout_id >= vdpy.vscrs_num) {
+               return;
+       }
+
        if (cur->data == NULL)
                return;
 
-       if (vdpy.cursor_tex)
-               SDL_DestroyTexture(vdpy.cursor_tex);
+       vscr = vdpy.vscrs + scanout_id;
+       if (vscr == NULL) {
+               return;
+       }
I think that this is not necessary. As it already assures that it is
scanout_id is in the range of supported vscrs_num, the vscrs should
exist.
[Sun, Peng] Will remove this check in next version.
+
+       if (vscr->cur_tex)
+               SDL_DestroyTexture(vscr->cur_tex);
 
-       vdpy.cursor_tex = SDL_CreateTexture(
-                       vdpy.dpy_renderer,
+       vscr->cur_tex = SDL_CreateTexture(
+                       vscr->renderer,
                        SDL_PIXELFORMAT_ARGB8888,
                        SDL_TEXTUREACCESS_STREAMING,
                        cur->width, cur->height);
-       if (vdpy.cursor_tex == NULL) {
+       if (vscr->cur_tex == NULL) {
                pr_err("Failed to create sdl_cursor surface for
%p.\n", cur);
                return;
        }
 
-       SDL_SetTextureBlendMode(vdpy.cursor_tex,
SDL_BLENDMODE_BLEND);
-       vdpy.cur = *cur;
-       SDL_UpdateTexture(vdpy.cursor_tex, NULL, cur->data, cur-
width * 4);
+       SDL_SetTextureBlendMode(vscr->cur_tex,
SDL_BLENDMODE_BLEND);
+       vscr->cur = *cur;
+       SDL_UpdateTexture(vscr->cur_tex, NULL, cur->data, cur-
width * 4);
  }
 
  void
  vdpy_cursor_move(int handle, int scanout_id, uint32_t x, uint32_t
y)
  {
+       struct vscreen *vscr;
+
        if (handle != vdpy.s.n_connect) {
                return;
        }
 
+       if (scanout_id >= vdpy.vscrs_num) {
+               return;
+       }
+
+       vscr = vdpy.vscrs + scanout_id;
        /* Only move the position of the cursor. The cursor_texture
         * will be handled in surface_update
         */
-       vdpy.cur.x = x;
-       vdpy.cur.y = y;
+       vscr->cur.x = x;
+       vscr->cur.y = y;
  }
 
  static void
@@ -847,35 +933,41 @@ vdpy_sdl_ui_refresh(void *data)
        struct timespec cur_time;
        uint64_t elapsed_time;
        SDL_Rect cursor_rect;
+       struct vscreen *vscr;
+       int i;
 
        ui_vdpy = (struct display *)data;
 
-       /* Skip it if no surface needs to be rendered */
-       if (ui_vdpy->dpy_texture == NULL)
-               return;
+       for (i = 0; i < vdpy.vscrs_num; i++) {
+               vscr = ui_vdpy->vscrs + i;
 
-       clock_gettime(CLOCK_MONOTONIC, &cur_time);
+               /* Skip it if no surface needs to be rendered */
+               if (vscr->surf_tex == NULL)
+                       continue;
 
-       elapsed_time = (cur_time.tv_sec - ui_vdpy-
last_time.tv_sec) * 1000000000 +
-                       cur_time.tv_nsec - ui_vdpy-
last_time.tv_nsec;
+               clock_gettime(CLOCK_MONOTONIC, &cur_time);
 
-       /* the time interval is less than 10ms. Skip it */
-       if (elapsed_time < 10000000)
-               return;
+               elapsed_time = (cur_time.tv_sec - vscr-
last_time.tv_sec) * 1000000000 +
+                               cur_time.tv_nsec - vscr-
last_time.tv_nsec;
-       SDL_RenderClear(ui_vdpy->dpy_renderer);
-       SDL_RenderCopy(ui_vdpy->dpy_renderer, ui_vdpy->dpy_texture,
NULL, NULL);
+               /* the time interval is less than 10ms. Skip it */
+               if (elapsed_time < 10000000)
+                       return;
 
-       /* This should be handled after rendering the
surface_texture.
-        * Otherwise it will be hidden
-        */
-       if (ui_vdpy->cursor_tex) {
-               vdpy_cursor_position_transformation(ui_vdpy,
&cursor_rect);
-               SDL_RenderCopy(ui_vdpy->dpy_renderer, ui_vdpy-
cursor_tex,
-                               NULL, &cursor_rect);
-       }
+               SDL_RenderClear(vscr->renderer);
+               SDL_RenderCopy(vscr->renderer, vscr->surf_tex,
NULL, NULL);
+
+               /* This should be handled after rendering the
surface_texture.
+                * Otherwise it will be hidden
+                */
+               if (vscr->cur_tex) {
+                       vdpy_cursor_position_transformation(ui_vdpy
, i, &cursor_rect);
+                       SDL_RenderCopy(vscr->renderer, vscr-
cur_tex,
+                                       NULL, &cursor_rect);
+               }
 
-       SDL_RenderPresent(ui_vdpy->dpy_renderer);
+               SDL_RenderPresent(vscr->renderer);
+       }
  }
 
  static void
@@ -911,57 +1003,67 @@ vdpy_sdl_display_thread(void *data)
        struct itimerspec ui_timer_spec;
        int max_width, max_height;
        int min_width, min_height;
+       struct vscreen *vscr;
+       int i;
 
-       max_width = MIN(vdpy.pscreen_rect.w, VDPY_MAX_WIDTH);
-       max_height = MIN(vdpy.pscreen_rect.h, VDPY_MAX_HEIGHT);
-       min_width = MAX(vdpy.pscreen_rect.w, VDPY_MIN_WIDTH);
-       min_height = MAX(vdpy.pscreen_rect.h, VDPY_MIN_HEIGHT);
-       if (vdpy.width && vdpy.height) {
-               /* clip the region between (640x480) and
(1920x1080) */
-               if (vdpy.width < min_width)
-                       vdpy.width = min_width;
-               if (vdpy.width > max_width)
-                       vdpy.width = max_width;
-               if (vdpy.height < min_height)
-                       vdpy.height = min_height;
-               if (vdpy.height > max_height)
-                       vdpy.height = max_height;
-       } else {
-               /* the default window(1280x720) is created with
undefined pos
-                * when no geometry info is passed
-                */
-               vdpy.org_x = 0xFFFF;
-               vdpy.org_y = 0xFFFF;
-               vdpy.width = VDPY_DEFAULT_WIDTH;
-               vdpy.height = VDPY_DEFAULT_HEIGHT;
-       }
+       for (i = 0; i < vdpy.vscrs_num; i++) {
+               vscr = vdpy.vscrs + i;
+               if (vscr == NULL) {
+                       continue;
+               }
 
-       win_flags = SDL_WINDOW_OPENGL |
-                   SDL_WINDOW_ALWAYS_ON_TOP |
-                   SDL_WINDOW_SHOWN;
-       if (vdpy.s.is_fullscreen) {
-               win_flags |= SDL_WINDOW_FULLSCREEN_DESKTOP;
-       }
-       vdpy.dpy_win = NULL;
-       vdpy.dpy_renderer = NULL;
-       vdpy.dpy_img = NULL;
-       vdpy.org_x = vdpy.pscreen_rect.x;
-       vdpy.org_y = vdpy.pscreen_rect.y;
-       vdpy.dpy_win = SDL_CreateWindow("ACRN_DM",
-                                       vdpy.org_x, vdpy.org_y,
-                                       vdpy.width, vdpy.height,
+               max_width = MIN(vscr->pscreen_rect.w,
VDPY_MAX_WIDTH);
+               max_height = MIN(vscr->pscreen_rect.h,
VDPY_MAX_HEIGHT);
+               min_width = MAX(vscr->pscreen_rect.w,
VDPY_MIN_WIDTH);
+               min_height = MAX(vscr->pscreen_rect.h,
VDPY_MIN_HEIGHT);
+               if (vscr->width && vscr->height) {
+                       /* clip the region between (640x480) and
(1920x1080) */
+                       if (vscr->width < min_width)
+                               vscr->width = min_width;
+                       if (vscr->width > max_width)
+                               vscr->width = max_width;
+                       if (vscr->height < min_height)
+                               vscr->height = min_height;
+                       if (vscr->height > max_height)
+                               vscr->height = max_height;
+               } else {
+                       /* the default window(1280x720) is created
with undefined pos
+                        * when no geometry info is passed
+                        */
+                       vscr->org_x = 0xFFFF;
+                       vscr->org_y = 0xFFFF;
+                       vscr->width = VDPY_DEFAULT_WIDTH;
+                       vscr->height = VDPY_DEFAULT_HEIGHT;
+               }
+
+               win_flags = SDL_WINDOW_OPENGL |
+                       SDL_WINDOW_ALWAYS_ON_TOP |
+                       SDL_WINDOW_SHOWN;
+               if (vscr->is_fullscreen) {
+                       win_flags |= SDL_WINDOW_FULLSCREEN_DESKTOP;
+               }
+               vscr->win = NULL;
+               vscr->renderer = NULL;
+               vscr->img = NULL;
+               vscr->org_x = vscr->pscreen_rect.x;
+               vscr->org_y = vscr->pscreen_rect.y;
+               vscr->win = SDL_CreateWindow("ACRN_DM",
+                                       vscr->org_x, vscr->org_y,
+                                       vscr->width, vscr->height,
                                        win_flags);
-       if (vdpy.dpy_win == NULL) {
-               pr_err("Failed to Create SDL_Window\n");
-               goto sdl_fail;
-       }
-       pr_info("SDL display bind to screen %d: [%d,%d,%d,%d].\n",
vdpy.pscreen_id,
-                       vdpy.org_x, vdpy.org_y, vdpy.width,
vdpy.height);
+               if (vscr->win == NULL) {
+                       pr_err("Failed to Create SDL_Window\n");
+                       goto sdl_fail;
+               }
+               pr_info("SDL display bind to screen %d:
[%d,%d,%d,%d].\n", vscr->pscreen_id,
+                               vscr->org_x, vscr->org_y, vscr-
width, vscr->height);
-       vdpy.dpy_renderer = SDL_CreateRenderer(vdpy.dpy_win, -1,
0);
-       if (vdpy.dpy_renderer == NULL) {
-               pr_err("Failed to Create GL_Renderer \n");
-               goto sdl_fail;
+               vscr->renderer = SDL_CreateRenderer(vscr->win, -1,
0);
+               if (vscr->renderer == NULL) {
+                       pr_err("Failed to Create GL_Renderer \n");
+                       goto sdl_fail;
+               }
+               clock_gettime(CLOCK_MONOTONIC, &vscr->last_time);
        }
        sdl_gl_display_init();
        pthread_mutex_init(&vdpy.vdisplay_mutex, NULL);
@@ -971,7 +1073,6 @@ vdpy_sdl_display_thread(void *data)
 
        vdpy.ui_timer_bh.task_cb = vdpy_sdl_ui_refresh;
        vdpy.ui_timer_bh.data = &vdpy;
-       clock_gettime(CLOCK_MONOTONIC, &vdpy.last_time);
        vdpy.ui_timer.clockid = CLOCK_MONOTONIC;
        acrn_timer_init(&vdpy.ui_timer, vdpy_sdl_ui_timer, &vdpy);
        ui_timer_spec.it_interval.tv_sec = 0;
@@ -1019,34 +1120,48 @@ vdpy_sdl_display_thread(void *data)
        /* SDL display_thread will exit because of DM request */
        pthread_mutex_destroy(&vdpy.vdisplay_mutex);
        pthread_cond_destroy(&vdpy.vdisplay_signal);
-       if (vdpy.dpy_img) {
-               pixman_image_unref(vdpy.dpy_img);
-               vdpy.dpy_img = NULL;
-       }
-       /* Continue to thread cleanup */
 
-       if (vdpy.dpy_texture) {
-               SDL_DestroyTexture(vdpy.dpy_texture);
-               vdpy.dpy_texture = NULL;
-       }
-       if (vdpy.cursor_tex) {
-               SDL_DestroyTexture(vdpy.cursor_tex);
-               vdpy.cursor_tex = NULL;
-       }
+       for (i = 0; i < vdpy.vscrs_num; i++) {
+               vscr = vdpy.vscrs + i;
+               if (vscr == NULL) {
+                       continue;
+               }
 
-       if (vdpy.egl_dmabuf_supported && (vdpy.cur_egl_img !=
EGL_NO_IMAGE_KHR))
-               vdpy.gl_ops.eglDestroyImageKHR(vdpy.eglDisplay,
-                                       vdpy.cur_egl_img);
+               if (vscr->img) {
+                       pixman_image_unref(vscr->img);
+                       vscr->img = NULL;
+               }
+               /* Continue to thread cleanup */
 
-sdl_fail:
+               if (vscr->surf_tex) {
+                       SDL_DestroyTexture(vscr->surf_tex);
+                       vscr->surf_tex = NULL;
+               }
+               if (vscr->cur_tex) {
+                       SDL_DestroyTexture(vscr->cur_tex);
+                       vscr->cur_tex = NULL;
+               }
 
-       if (vdpy.dpy_renderer) {
-               SDL_DestroyRenderer(vdpy.dpy_renderer);
-               vdpy.dpy_renderer = NULL;
+               if (vdpy.egl_dmabuf_supported && (vscr->egl_img !=
EGL_NO_IMAGE_KHR))
+                       vdpy.gl_ops.eglDestroyImageKHR(vdpy.eglDisp
lay,
+                                               vscr->egl_img);
        }
-       if (vdpy.dpy_win) {
-               SDL_DestroyWindow(vdpy.dpy_win);
-               vdpy.dpy_win = NULL;
+
+sdl_fail:
+       for (i = 0; i < vdpy.vscrs_num; i++) {
+               vscr = vdpy.vscrs + i;
+               if (vscr == NULL) {
+                       continue;
+               }
+
+               if (vscr->renderer) {
+                       SDL_DestroyRenderer(vscr->renderer);
+                       vscr->renderer = NULL;
+               }
+               if (vscr->win) {
+                       SDL_DestroyWindow(vscr->win);
+                       vscr->win = NULL;
+               }
        }
 
        /* This is used to workaround the TLS issue of libEGL +
libGLdispatch
@@ -1113,7 +1228,7 @@ vdpy_init(int *supported_wins)
 
        vdpy.s.n_connect++;
        if (supported_wins)
-               *supported_wins = 1;
+               *supported_wins = vdpy.vscrs_num;
        return vdpy.s.n_connect;
  }
 
@@ -1146,6 +1261,8 @@ int
  gfx_ui_init()
  {
        SDL_SysWMinfo info;
+       struct vscreen *vscr;
+       int i;
 
        setenv("SDL_VIDEO_X11_FORCE_EGL", "1", 1);
        setenv("SDL_OPENGL_ES_DRIVER", "1", 1);
@@ -1157,14 +1274,17 @@ gfx_ui_init()
                return -1;
        }
 
-       SDL_GetDisplayBounds(vdpy.pscreen_id, &vdpy.pscreen_rect);
+       for (i = 0; i < vdpy.vscrs_num; i++) {
+               vscr = vdpy.vscrs + i;
+               SDL_GetDisplayBounds(vscr->pscreen_id, &vscr-
pscreen_rect);
-       if (vdpy.pscreen_rect.w < VDPY_MIN_WIDTH ||
-           vdpy.pscreen_rect.h < VDPY_MIN_HEIGHT) {
-               pr_err("Too small resolutions. Please check the "
-                      " graphics system\n");
-               SDL_Quit();
-               return -1;
+               if (vscr->pscreen_rect.w < VDPY_MIN_WIDTH ||
+                   vscr->pscreen_rect.h < VDPY_MIN_HEIGHT) {
+                       pr_err("Too small resolutions. Please check
the "
+                               " graphics system\n");
+                       SDL_Quit();
+                       return -1;
+               }
        }
 
        SDL_SetHint(SDL_HINT_GRAB_KEYBOARD, "1");
@@ -1196,6 +1316,7 @@ gfx_ui_deinit()
                return;
        }
 
+       free(vdpy.vscrs);
        SDL_Quit();
        pr_info("SDL_Quit\r\n");
  }
@@ -1204,35 +1325,41 @@ int vdpy_parse_cmd_option(const char *opts)
  {
        char *str;
        int snum, error;
+       struct vscreen *vscr;
 
Can this split into another patch?
That is to say: This patch still assumes that it only support one
vscreen. And another patches tries to parse the correct number and
vscreen info.
[Sun, Peng] These changes are for one vscreen data struct, not for
multi-vscreen parse. 3/3 patch is for to parse 2 vscreen.

        error = 0;
+       vdpy.vscrs = calloc(VSCREEN_MAX_NUM, sizeof(struct
vscreen));
+       vdpy.vscrs_num = 0;
 
        str = strcasestr(opts, "geometry=");
+       vscr = vdpy.vscrs + vdpy.vscrs_num;
        if (opts && strcasestr(opts, "geometry=fullscreen")) {
-               snum = sscanf(str, "geometry=fullscreen:%d",
&vdpy.pscreen_id);
+               snum = sscanf(str, "geometry=fullscreen:%d", &vscr-
pscreen_id);
                if (snum != 1) {
-                       vdpy.pscreen_id = 0;
+                       vscr->pscreen_id = 0;
                }
-               vdpy.width = VDPY_MAX_WIDTH;
-               vdpy.height = VDPY_MAX_HEIGHT;
-               vdpy.s.is_fullscreen = true;
+               vscr->width = VDPY_MAX_WIDTH;
+               vscr->height = VDPY_MAX_HEIGHT;
+               vscr->is_fullscreen = true;
+               vdpy.vscrs_num++;
                pr_info("virtual display: fullscreen.\n");
        } else if (opts && strcasestr(opts, "geometry=")) {
                snum = sscanf(str, "geometry=%dx%d+%d+%d",
-                               &vdpy.width, &vdpy.height,
-                               &vdpy.org_x, &vdpy.org_y);
+                               &vscr->width, &vscr->height,
+                               &vscr->org_x, &vscr->org_y);
                if (snum != 4) {
                        pr_err("incorrect geometry option. Should
be"
                                        " WxH+x+y\n");
                        error = -1;
                }
-               vdpy.s.is_fullscreen = false;
+               vscr->is_fullscreen = false;
+               vdpy.vscrs_num++;
                pr_info("virtual display: windowed.\n");
        }
 
-       vdpy.info.xoff = 0;
-       vdpy.info.yoff = 0;
-       vdpy.info.width = vdpy.width;
-       vdpy.info.height = vdpy.height;
+       vscr->info.xoff = 0;
+       vscr->info.yoff = 0;
+       vscr->info.width = vdpy.vscrs->width;
+       vscr->info.height = vdpy.vscrs->height;
        return error;
  }
--
Sun Peng <peng.p.sun@...>
SSE/ACRN Upstream


[PATCH v2] config_tool-Instruction-missing-for-L2-only-users

Chuang Ke
 

v1-->v2:
1. instruction displayed regardless of if L3 or L2 cache were available, now it displayed instructions accordingly no matter how many caches
2. let instruction displayed only once above the topmost CAT configuration table

Signed-off-by: Chuang-Ke <chuangx.ke@...>
Tracked-On: #7921
---
.../pages/Config/ConfigForm/CustomWidget/CAT.vue | 14 +++++++++++---
1 file changed, 11 insertions(+), 3 deletions(-)

diff --git a/misc/config_tools/configurator/packages/configurator/src/pages/Config/ConfigForm/CustomWidget/CAT.vue b/misc/config_tools/configurator/packages/configurator/src/pages/Config/ConfigForm/CustomWidget/CAT.vue
index 5a64a3c2f..dcda14ea8 100644
--- a/misc/config_tools/configurator/packages/configurator/src/pages/Config/ConfigForm/CustomWidget/CAT.vue
+++ b/misc/config_tools/configurator/packages/configurator/src/pages/Config/ConfigForm/CustomWidget/CAT.vue
@@ -60,8 +60,8 @@
<div class="py-3" v-if="CAT_INFO.errorMsg">
{{ CAT_INFO.errorMsg }}
</div>
- <div class="py-4" v-for="CACHE_ALLOCATION in CAT_INFO.regions" v-if="RDT_ENABLED==='y'">
- <p v-if="CACHE_ALLOCATION.level===3||CACHE_ALLOCATION.level===2">
+ <div class="py-4" v-for="(CACHE_ALLOCATION,index) in CAT_INFO.regions" v-if="RDT_ENABLED==='y'">
+ <p v-if="showInstruction(CACHE_ALLOCATION.level,index) ">
Drag the ends of the boxes to cover the cache chunks you want to allocate to specific VMs. If you have a
real-time
VM,ensure its cache chunks do not overlap with any other VM's cache chunks.
@@ -218,10 +218,17 @@ export default {
return {
CAT_INFO: {errorMsg: null, regions: [], summary: {}},
SSRAMInfo: this.rootSchema.definitions['SSRAMInfo'],
- RDTType: this.rootSchema.definitions['RDTType']
+ RDTType: this.rootSchema.definitions['RDTType'],
+ InstructionLocation: {},
}
},
methods: {
+ showInstruction(level, index) {
+ if (!(level in this.InstructionLocation)) {
+ this.InstructionLocation[level] = index
+ }
+ return this.InstructionLocation[level]===index
+ },
boardUpdate() {
this.updateCatInfo()
},
@@ -333,6 +340,7 @@ export default {
},
updateCatInfo() {
this.CAT_INFO = configurator.cat.getCATUIData()
+ this.InstructionLocation={}
}
}
}
--
2.25.1


Re: [PATCH v1 3/3] dm: vdisplay: multi-vdisplay support.

Zhao, Yakui
 

On 2022/8/8 13:36, peng.p.sun@... wrote:
From: Sun Peng <peng.p.sun@...>
Allow one VM have more than 1 virtual display for output. Till now, the
max virtual display number is 2. So guest VM can use dual display for
mirror and extend desktop mode. To specify multi-vdisplay, need use
acrn-dm parameters like this:
For fullscreen mode:
After multi vscreens are supported, it will be better that the error message is printed with the vscr_id.
Otherwise it is difficult to check where is the problem.

virtio-gpu,geometry=fullscreen:monitor_id1,geometry=fullscreen:monitor_id2
For window mode:
virtio-gpu,geometry=<width>x<height>+<x_off>+<y_off>,geometry=<width>x<height>+<x_off>+<y_off>
Signed-off-by: Sun Peng <peng.p.sun@...>
---
devicemodel/hw/vdisplay_sdl.c | 67 +++++++++++++++++++++--------------
1 file changed, 40 insertions(+), 27 deletions(-)
diff --git a/devicemodel/hw/vdisplay_sdl.c b/devicemodel/hw/vdisplay_sdl.c
index 28457c52e..c7a279ab6 100644
--- a/devicemodel/hw/vdisplay_sdl.c
+++ b/devicemodel/hw/vdisplay_sdl.c
@@ -32,7 +32,7 @@
#define VDPY_MIN_WIDTH 640
#define VDPY_MIN_HEIGHT 480
#define transto_10bits(color) (uint16_t)(color * 1024 + 0.5)
-#define VSCREEN_MAX_NUM 1
+#define VSCREEN_MAX_NUM 2
static unsigned char default_raw_argb[VDPY_DEFAULT_WIDTH * VDPY_DEFAULT_HEIGHT * 4];
@@ -1323,7 +1323,7 @@ gfx_ui_deinit()
int vdpy_parse_cmd_option(const char *opts)
{
- char *str;
+ char *str, *stropts, *tmp;
int snum, error;
struct vscreen *vscr;
@@ -1331,35 +1331,48 @@ int vdpy_parse_cmd_option(const char *opts)
vdpy.vscrs = calloc(VSCREEN_MAX_NUM, sizeof(struct vscreen));
vdpy.vscrs_num = 0;
- str = strcasestr(opts, "geometry=");
- vscr = vdpy.vscrs + vdpy.vscrs_num;
- if (opts && strcasestr(opts, "geometry=fullscreen")) {
- snum = sscanf(str, "geometry=fullscreen:%d", &vscr->pscreen_id);
- if (snum != 1) {
+ stropts = strdup(opts);
+ while ((str = strsep(&stropts, ",")) != NULL) {
+ vscr = vdpy.vscrs + vdpy.vscrs_num;
+ tmp = strcasestr(str, "geometry=");
+ if (str && strcasestr(str, "geometry=fullscreen")) {
+ snum = sscanf(tmp, "geometry=fullscreen:%d", &vscr->pscreen_id);
+ if (snum != 1) {
+ vscr->pscreen_id = 0;
+ }
+ vscr->width = VDPY_MAX_WIDTH;
+ vscr->height = VDPY_MAX_HEIGHT;
+ vscr->is_fullscreen = true;
+ pr_info("virtual display: fullscreen.\n");
+ vscr->info.xoff = vscr->org_x;
+ vscr->info.yoff = vscr->org_y;
+ vscr->info.width = vscr->width;
+ vscr->info.height = vscr->height;
+ vdpy.vscrs_num++;
+ } else if (str && strcasestr(str, "geometry=")) {
+ snum = sscanf(tmp, "geometry=%dx%d+%d+%d",
+ &vscr->width, &vscr->height,
+ &vscr->org_x, &vscr->org_y);
+ if (snum != 4) {
+ pr_err("incorrect geometry option. Should be"
+ " WxH+x+y\n");
+ error = -1;
+ }
+ vscr->is_fullscreen = false;
vscr->pscreen_id = 0;
+ pr_info("virtual display: windowed.\n");
+ vscr->info.xoff = vscr->org_x;
+ vscr->info.yoff = vscr->org_y;
+ vscr->info.width = vscr->width;
+ vscr->info.height = vscr->height;
+ vdpy.vscrs_num++;
}
- vscr->width = VDPY_MAX_WIDTH;
- vscr->height = VDPY_MAX_HEIGHT;
- vscr->is_fullscreen = true;
- vdpy.vscrs_num++;
- pr_info("virtual display: fullscreen.\n");
- } else if (opts && strcasestr(opts, "geometry=")) {
- snum = sscanf(str, "geometry=%dx%d+%d+%d",
- &vscr->width, &vscr->height,
- &vscr->org_x, &vscr->org_y);
- if (snum != 4) {
- pr_err("incorrect geometry option. Should be"
- " WxH+x+y\n");
- error = -1;
+ if (vdpy.vscrs_num > VSCREEN_MAX_NUM) {
+ pr_err("Too many virtual display that acrn-dm can't support!\n");
+ break;
}
- vscr->is_fullscreen = false;
- vdpy.vscrs_num++;
- pr_info("virtual display: windowed.\n");
}
+ free(stropts);
- vscr->info.xoff = 0;
- vscr->info.yoff = 0;
- vscr->info.width = vdpy.vscrs->width;
- vscr->info.height = vdpy.vscrs->height;
return error;
}


Re: [PATCH v1 2/3] dm: vdisplay: refine vdisplay core concept abstractions

Zhao, Yakui
 

On 2022/8/8 13:36, peng.p.sun@... wrote:
From: Sun Peng <peng.p.sun@...>
Add new concept "vscreen" to abstract all specs about screen in a
display server. This can provide convenience to add more screens
for one VM.
Signed-off-by: Sun Peng <peng.p.sun@...>
---
devicemodel/hw/vdisplay_sdl.c | 503 +++++++++++++++++++++-------------
1 file changed, 315 insertions(+), 188 deletions(-)
diff --git a/devicemodel/hw/vdisplay_sdl.c b/devicemodel/hw/vdisplay_sdl.c
index 7a098f4b2..28457c52e 100644
--- a/devicemodel/hw/vdisplay_sdl.c
+++ b/devicemodel/hw/vdisplay_sdl.c
@@ -32,6 +32,7 @@
#define VDPY_MIN_WIDTH 640
#define VDPY_MIN_HEIGHT 480
#define transto_10bits(color) (uint16_t)(color * 1024 + 0.5)
+#define VSCREEN_MAX_NUM 1
static unsigned char default_raw_argb[VDPY_DEFAULT_WIDTH * VDPY_DEFAULT_HEIGHT * 4];
@@ -40,8 +41,6 @@ struct state {
bool is_active;
bool is_wayland;
bool is_x11;
- bool is_fullscreen;
- uint64_t updates;
int n_connect;
};
@@ -51,27 +50,39 @@ struct egl_display_ops {
PFNGLEGLIMAGETARGETTEXTURE2DOESPROC glEGLImageTargetTexture2DOES;
};
-static struct display {
+struct vscreen {
+ struct display_info info;
int pscreen_id;
SDL_Rect pscreen_rect;
- struct display_info info;
- struct state s;
- SDL_Texture *dpy_texture;
- SDL_Window *dpy_win;
- SDL_Renderer *dpy_renderer;
- pixman_image_t *dpy_img;
- pthread_t tid;
- int width, height; // Width/height of dpy_win
- int org_x, org_y;
- int guest_width, guest_height;
+ bool is_fullscreen;
+ int org_x;
+ int org_y;
+ int width;
+ int height;
+ int guest_width;
+ int guest_height;
struct surface surf;
struct cursor cur;
- SDL_Texture *cursor_tex;
+ SDL_Texture *surf_tex;
+ SDL_Texture *cur_tex;
+ int surf_updates;
+ int cur_updates;
+ SDL_Window *win;
+ SDL_Renderer *renderer;
+ pixman_image_t *img;
+ EGLImage egl_img;
+ /* Record the update_time that is activated from guest_vm */
+ struct timespec last_time;
+};
+
+static struct display {
+ struct state s;
+ struct vscreen *vscrs;
+ int vscrs_num;
+ pthread_t tid;
/* Add one UI_timer(33ms) to render the buffers from guest_vm */
struct acrn_timer ui_timer;
struct vdpy_display_bh ui_timer_bh;
- /* Record the update_time that is activated from guest_vm */
- struct timespec last_time;
// protect the request_list
pthread_mutex_t vdisplay_mutex;
// receive the signal that request is submitted
@@ -82,14 +93,11 @@ static struct display {
SDL_GLContext eglContext;
EGLDisplay eglDisplay;
struct egl_display_ops gl_ops;
- EGLImage cur_egl_img;
} vdpy = {
.s.is_ui_realized = false,
.s.is_active = false,
.s.is_wayland = false,
.s.is_x11 = false,
- .s.is_fullscreen = false,
- .s.updates = 0,
.s.n_connect = 0
};
@@ -514,10 +522,19 @@ void
vdpy_get_edid(int handle, int scanout_id, uint8_t *edid, size_t size)
{
struct edid_info edid_info;
+ struct vscreen *vscr;
+
+ if (scanout_id >= vdpy.vscrs_num)
+ return;
+
+ vscr = vdpy.vscrs + scanout_id;
+ if (vscr == NULL) {
+ return;
+ }
if (handle == vdpy.s.n_connect) {
- edid_info.prefx = vdpy.info.width;
- edid_info.prefy = vdpy.info.height;
+ edid_info.prefx = vscr->info.width;
+ edid_info.prefy = vscr->info.height;
edid_info.maxx = VDPY_MAX_WIDTH;
edid_info.maxy = VDPY_MAX_HEIGHT;
} else {
@@ -537,11 +554,21 @@ vdpy_get_edid(int handle, int scanout_id, uint8_t *edid, size_t size)
void
vdpy_get_display_info(int handle, int scanout_id, struct display_info *info)
{
+ struct vscreen *vscr;
+
+ if (scanout_id >= vdpy.vscrs_num)
+ return;
+
+ vscr = vdpy.vscrs + scanout_id;
+ if (vscr == NULL) {
+ return;
+ }
+
if (handle == vdpy.s.n_connect) {
- info->xoff = vdpy.info.xoff;
- info->yoff = vdpy.info.yoff;
- info->width = vdpy.info.width;
- info->height = vdpy.info.height;
+ info->xoff = vscr->info.xoff;
+ info->yoff = vscr->info.yoff;
+ info->width = vscr->info.width;
+ info->height = vscr->info.height;
} else {
info->xoff = 0;
info->yoff = 0;
@@ -554,6 +581,8 @@ static void
sdl_gl_display_init(void)
{
struct egl_display_ops *gl_ops = &vdpy.gl_ops;
+ struct vscreen *vscr;
+ int i;
/* obtain the eglDisplay/eglContext */
vdpy.eglDisplay = eglGetCurrentDisplay();
@@ -570,7 +599,15 @@ sdl_gl_display_init(void)
gl_ops->glEGLImageTargetTexture2DOES = (PFNGLEGLIMAGETARGETTEXTURE2DOESPROC)
eglGetProcAddress("glEGLImageTargetTexture2DOES");
- vdpy.cur_egl_img = EGL_NO_IMAGE_KHR;
+ for (i = 0; i < vdpy.vscrs_num; i++) {
+ vscr = vdpy.vscrs + i;
+ if (vscr == NULL) {
+ continue;
+ }
+
+ vscr->egl_img = EGL_NO_IMAGE_KHR;
+ }
+
if ((gl_ops->eglCreateImageKHR == NULL) ||
(gl_ops->eglDestroyImageKHR == NULL) ||
(gl_ops->glEGLImageTargetTexture2DOES == NULL)) {
@@ -588,6 +625,7 @@ vdpy_surface_set(int handle, int scanout_id, struct surface *surf)
pixman_image_t *src_img;
int format;
int access, i;
+ struct vscreen *vscr;
if (handle != vdpy.s.n_connect) {
return;
@@ -599,9 +637,18 @@ vdpy_surface_set(int handle, int scanout_id, struct surface *surf)
return;
}
+ if (scanout_id >= vdpy.vscrs_num) {
+ return;
+ }
+
+ vscr = vdpy.vscrs + scanout_id;
+ if (vscr == NULL) {
+ return;
+ }
+
if (surf == NULL ) {
- vdpy.surf.width = 0;
- vdpy.surf.height = 0;
+ vscr->surf.width = 0;
+ vscr->surf.height = 0;
/* Need to use the default 640x480 for the SDL_Texture */
src_img = pixman_image_create_bits(PIXMAN_a8r8g8b8,
VDPY_MIN_WIDTH, VDPY_MIN_HEIGHT,
@@ -611,8 +658,8 @@ vdpy_surface_set(int handle, int scanout_id, struct surface *surf)
pr_err("failed to create pixman_image\n");
return;
}
- vdpy.guest_width = VDPY_MIN_WIDTH;
- vdpy.guest_height = VDPY_MIN_HEIGHT;
+ vscr->guest_width = VDPY_MIN_WIDTH;
+ vscr->guest_height = VDPY_MIN_HEIGHT;
} else if (surf->surf_type == SURFACE_PIXMAN) {
src_img = pixman_image_create_bits(surf->surf_format,
surf->width, surf->height, surf->pixel,
@@ -621,21 +668,21 @@ vdpy_surface_set(int handle, int scanout_id, struct surface *surf)
pr_err("failed to create pixman_image\n");
return;
}
- vdpy.surf = *surf;
- vdpy.guest_width = surf->width;
- vdpy.guest_height = surf->height;
+ vscr->surf = *surf;
+ vscr->guest_width = surf->width;
+ vscr->guest_height = surf->height;
} else if (surf->surf_type == SURFACE_DMABUF) {
src_img = NULL;
- vdpy.surf = *surf;
- vdpy.guest_width = surf->width;
- vdpy.guest_height = surf->height;
+ vscr->surf = *surf;
+ vscr->guest_width = surf->width;
+ vscr->guest_height = surf->height;
} else {
/* Unsupported type */
return;
}
- if (vdpy.dpy_texture) {
- SDL_DestroyTexture(vdpy.dpy_texture);
+ if (vscr->surf_tex) {
+ SDL_DestroyTexture(vscr->surf_tex);
}
if (surf && (surf->surf_type == SURFACE_DMABUF)) {
access = SDL_TEXTUREACCESS_STATIC;
@@ -666,23 +713,23 @@ vdpy_surface_set(int handle, int scanout_id, struct surface *surf)
pixman_image_get_format(src_img));
}
}
- vdpy.dpy_texture = SDL_CreateTexture(vdpy.dpy_renderer,
+ vscr->surf_tex = SDL_CreateTexture(vscr->renderer,
format, access,
- vdpy.guest_width, vdpy.guest_height);
+ vscr->guest_width, vscr->guest_height);
- if (vdpy.dpy_texture == NULL) {
+ if (vscr->surf_tex == NULL) {
pr_err("Failed to create SDL_texture for surface.\n");
}
/* For the surf_switch, it will be updated in surface_update */
if (!surf) {
- SDL_UpdateTexture(vdpy.dpy_texture, NULL,
+ SDL_UpdateTexture(vscr->surf_tex, NULL,
pixman_image_get_data(src_img),
pixman_image_get_stride(src_img));
- SDL_RenderClear(vdpy.dpy_renderer);
- SDL_RenderCopy(vdpy.dpy_renderer, vdpy.dpy_texture, NULL, NULL);
- SDL_RenderPresent(vdpy.dpy_renderer);
+ SDL_RenderClear(vscr->renderer);
+ SDL_RenderCopy(vscr->renderer, vscr->surf_tex, NULL, NULL);
+ SDL_RenderPresent(vscr->renderer);
} else if (surf->surf_type == SURFACE_DMABUF) {
EGLImageKHR egl_img = EGL_NO_IMAGE_KHR;
EGLint attrs[64];
@@ -713,46 +760,58 @@ vdpy_surface_set(int handle, int scanout_id, struct surface *surf)
return;
}
- SDL_GL_BindTexture(vdpy.dpy_texture, NULL, NULL);
+ SDL_GL_BindTexture(vscr->surf_tex, NULL, NULL);
gl_ops->glEGLImageTargetTexture2DOES(GL_TEXTURE_EXTERNAL_OES, egl_img);
- if (vdpy.cur_egl_img != EGL_NO_IMAGE_KHR)
+ if (vscr->egl_img != EGL_NO_IMAGE_KHR)
gl_ops->eglDestroyImageKHR(vdpy.eglDisplay,
- vdpy.cur_egl_img);
+ vscr->egl_img);
/* In theory the created egl_img can be released after it is bound
* to texture.
* Now it is released next time so that it is controlled correctly
*/
- vdpy.cur_egl_img = egl_img;
+ vscr->egl_img = egl_img;
}
- if (vdpy.dpy_img)
- pixman_image_unref(vdpy.dpy_img);
+ if (vscr->img)
+ pixman_image_unref(vscr->img);
if (surf == NULL) {
- SDL_SetWindowTitle(vdpy.dpy_win,
+ SDL_SetWindowTitle(vscr->win,
"Not activate display yet!");
} else {
- SDL_SetWindowTitle(vdpy.dpy_win,
+ SDL_SetWindowTitle(vscr->win,
"ACRN Virtual Monitor");
}
/* Replace the cur_img with the created_img */
- vdpy.dpy_img = src_img;
+ vscr->img = src_img;
}
void
-vdpy_cursor_position_transformation(struct display *vdpy, SDL_Rect *rect)
+vdpy_cursor_position_transformation(struct display *vdpy, int scanout_id, SDL_Rect *rect)
{
- rect->x = (vdpy->cur.x * vdpy->width) / vdpy->guest_width;
- rect->y = (vdpy->cur.y * vdpy->height) / vdpy->guest_height;
- rect->w = (vdpy->cur.width * vdpy->width) / vdpy->guest_width;
- rect->h = (vdpy->cur.height * vdpy->height) / vdpy->guest_height;
+ struct vscreen *vscr;
+
+ if (scanout_id >= vdpy->vscrs_num) {
+ return;
+ }
+
+ vscr = vdpy->vscrs + scanout_id;
+ if(vscr == NULL) {
+ return;
+ }
+
+ rect->x = (vscr->cur.x * vscr->width) / vscr->guest_width;
+ rect->y = (vscr->cur.y * vscr->height) / vscr->guest_height;
+ rect->w = (vscr->cur.width * vscr->width) / vscr->guest_width;
+ rect->h = (vscr->cur.height * vscr->height) / vscr->guest_height;
}
void
vdpy_surface_update(int handle, int scanout_id, struct surface *surf)
{
SDL_Rect cursor_rect;
+ struct vscreen *vscr;
if (handle != vdpy.s.n_connect) {
return;
@@ -769,32 +828,43 @@ vdpy_surface_update(int handle, int scanout_id, struct surface *surf)
return;
}
+ if (scanout_id >= vdpy.vscrs_num) {
+ return;
+ }
+
+ vscr = vdpy.vscrs + scanout_id;
+ if (vscr == NULL) {
+ return;
+ }
+
if (surf->surf_type == SURFACE_PIXMAN)
- SDL_UpdateTexture(vdpy.dpy_texture, NULL,
+ SDL_UpdateTexture(vscr->surf_tex, NULL,
surf->pixel,
surf->stride);
- SDL_RenderClear(vdpy.dpy_renderer);
- SDL_RenderCopy(vdpy.dpy_renderer, vdpy.dpy_texture, NULL, NULL);
+ SDL_RenderClear(vscr->renderer);
+ SDL_RenderCopy(vscr->renderer, vscr->surf_tex, NULL, NULL);
/* This should be handled after rendering the surface_texture.
* Otherwise it will be hidden
*/
- if (vdpy.cursor_tex) {
- vdpy_cursor_position_transformation(&vdpy, &cursor_rect);
- SDL_RenderCopy(vdpy.dpy_renderer, vdpy.cursor_tex,
+ if (vscr->cur_tex) {
+ vdpy_cursor_position_transformation(&vdpy, scanout_id, &cursor_rect);
+ SDL_RenderCopy(vscr->renderer, vscr->cur_tex,
NULL, &cursor_rect);
}
- SDL_RenderPresent(vdpy.dpy_renderer);
+ SDL_RenderPresent(vscr->renderer);
/* update the rendering time */
- clock_gettime(CLOCK_MONOTONIC, &vdpy.last_time);
+ clock_gettime(CLOCK_MONOTONIC, &vscr->last_time);
}
void
vdpy_cursor_define(int handle, int scanout_id, struct cursor *cur)
{
+ struct vscreen *vscr;
+
if (handle != vdpy.s.n_connect) {
return;
}
@@ -805,39 +875,55 @@ vdpy_cursor_define(int handle, int scanout_id, struct cursor *cur)
return;
}
+ if (scanout_id >= vdpy.vscrs_num) {
+ return;
+ }
+
if (cur->data == NULL)
return;
- if (vdpy.cursor_tex)
- SDL_DestroyTexture(vdpy.cursor_tex);
+ vscr = vdpy.vscrs + scanout_id;
+ if (vscr == NULL) {
+ return;
+ }
I think that this is not necessary. As it already assures that it is scanout_id is in the range of supported vscrs_num, the vscrs should exist.

+
+ if (vscr->cur_tex)
+ SDL_DestroyTexture(vscr->cur_tex);
- vdpy.cursor_tex = SDL_CreateTexture(
- vdpy.dpy_renderer,
+ vscr->cur_tex = SDL_CreateTexture(
+ vscr->renderer,
SDL_PIXELFORMAT_ARGB8888,
SDL_TEXTUREACCESS_STREAMING,
cur->width, cur->height);
- if (vdpy.cursor_tex == NULL) {
+ if (vscr->cur_tex == NULL) {
pr_err("Failed to create sdl_cursor surface for %p.\n", cur);
return;
}
- SDL_SetTextureBlendMode(vdpy.cursor_tex, SDL_BLENDMODE_BLEND);
- vdpy.cur = *cur;
- SDL_UpdateTexture(vdpy.cursor_tex, NULL, cur->data, cur->width * 4);
+ SDL_SetTextureBlendMode(vscr->cur_tex, SDL_BLENDMODE_BLEND);
+ vscr->cur = *cur;
+ SDL_UpdateTexture(vscr->cur_tex, NULL, cur->data, cur->width * 4);
}
void
vdpy_cursor_move(int handle, int scanout_id, uint32_t x, uint32_t y)
{
+ struct vscreen *vscr;
+
if (handle != vdpy.s.n_connect) {
return;
}
+ if (scanout_id >= vdpy.vscrs_num) {
+ return;
+ }
+
+ vscr = vdpy.vscrs + scanout_id;
/* Only move the position of the cursor. The cursor_texture
* will be handled in surface_update
*/
- vdpy.cur.x = x;
- vdpy.cur.y = y;
+ vscr->cur.x = x;
+ vscr->cur.y = y;
}
static void
@@ -847,35 +933,41 @@ vdpy_sdl_ui_refresh(void *data)
struct timespec cur_time;
uint64_t elapsed_time;
SDL_Rect cursor_rect;
+ struct vscreen *vscr;
+ int i;
ui_vdpy = (struct display *)data;
- /* Skip it if no surface needs to be rendered */
- if (ui_vdpy->dpy_texture == NULL)
- return;
+ for (i = 0; i < vdpy.vscrs_num; i++) {
+ vscr = ui_vdpy->vscrs + i;
- clock_gettime(CLOCK_MONOTONIC, &cur_time);
+ /* Skip it if no surface needs to be rendered */
+ if (vscr->surf_tex == NULL)
+ continue;
- elapsed_time = (cur_time.tv_sec - ui_vdpy->last_time.tv_sec) * 1000000000 +
- cur_time.tv_nsec - ui_vdpy->last_time.tv_nsec;
+ clock_gettime(CLOCK_MONOTONIC, &cur_time);
- /* the time interval is less than 10ms. Skip it */
- if (elapsed_time < 10000000)
- return;
+ elapsed_time = (cur_time.tv_sec - vscr->last_time.tv_sec) * 1000000000 +
+ cur_time.tv_nsec - vscr->last_time.tv_nsec;
- SDL_RenderClear(ui_vdpy->dpy_renderer);
- SDL_RenderCopy(ui_vdpy->dpy_renderer, ui_vdpy->dpy_texture, NULL, NULL);
+ /* the time interval is less than 10ms. Skip it */
+ if (elapsed_time < 10000000)
+ return;
- /* This should be handled after rendering the surface_texture.
- * Otherwise it will be hidden
- */
- if (ui_vdpy->cursor_tex) {
- vdpy_cursor_position_transformation(ui_vdpy, &cursor_rect);
- SDL_RenderCopy(ui_vdpy->dpy_renderer, ui_vdpy->cursor_tex,
- NULL, &cursor_rect);
- }
+ SDL_RenderClear(vscr->renderer);
+ SDL_RenderCopy(vscr->renderer, vscr->surf_tex, NULL, NULL);
+
+ /* This should be handled after rendering the surface_texture.
+ * Otherwise it will be hidden
+ */
+ if (vscr->cur_tex) {
+ vdpy_cursor_position_transformation(ui_vdpy, i, &cursor_rect);
+ SDL_RenderCopy(vscr->renderer, vscr->cur_tex,
+ NULL, &cursor_rect);
+ }
- SDL_RenderPresent(ui_vdpy->dpy_renderer);
+ SDL_RenderPresent(vscr->renderer);
+ }
}
static void
@@ -911,57 +1003,67 @@ vdpy_sdl_display_thread(void *data)
struct itimerspec ui_timer_spec;
int max_width, max_height;
int min_width, min_height;
+ struct vscreen *vscr;
+ int i;
- max_width = MIN(vdpy.pscreen_rect.w, VDPY_MAX_WIDTH);
- max_height = MIN(vdpy.pscreen_rect.h, VDPY_MAX_HEIGHT);
- min_width = MAX(vdpy.pscreen_rect.w, VDPY_MIN_WIDTH);
- min_height = MAX(vdpy.pscreen_rect.h, VDPY_MIN_HEIGHT);
- if (vdpy.width && vdpy.height) {
- /* clip the region between (640x480) and (1920x1080) */
- if (vdpy.width < min_width)
- vdpy.width = min_width;
- if (vdpy.width > max_width)
- vdpy.width = max_width;
- if (vdpy.height < min_height)
- vdpy.height = min_height;
- if (vdpy.height > max_height)
- vdpy.height = max_height;
- } else {
- /* the default window(1280x720) is created with undefined pos
- * when no geometry info is passed
- */
- vdpy.org_x = 0xFFFF;
- vdpy.org_y = 0xFFFF;
- vdpy.width = VDPY_DEFAULT_WIDTH;
- vdpy.height = VDPY_DEFAULT_HEIGHT;
- }
+ for (i = 0; i < vdpy.vscrs_num; i++) {
+ vscr = vdpy.vscrs + i;
+ if (vscr == NULL) {
+ continue;
+ }
- win_flags = SDL_WINDOW_OPENGL |
- SDL_WINDOW_ALWAYS_ON_TOP |
- SDL_WINDOW_SHOWN;
- if (vdpy.s.is_fullscreen) {
- win_flags |= SDL_WINDOW_FULLSCREEN_DESKTOP;
- }
- vdpy.dpy_win = NULL;
- vdpy.dpy_renderer = NULL;
- vdpy.dpy_img = NULL;
- vdpy.org_x = vdpy.pscreen_rect.x;
- vdpy.org_y = vdpy.pscreen_rect.y;
- vdpy.dpy_win = SDL_CreateWindow("ACRN_DM",
- vdpy.org_x, vdpy.org_y,
- vdpy.width, vdpy.height,
+ max_width = MIN(vscr->pscreen_rect.w, VDPY_MAX_WIDTH);
+ max_height = MIN(vscr->pscreen_rect.h, VDPY_MAX_HEIGHT);
+ min_width = MAX(vscr->pscreen_rect.w, VDPY_MIN_WIDTH);
+ min_height = MAX(vscr->pscreen_rect.h, VDPY_MIN_HEIGHT);
+ if (vscr->width && vscr->height) {
+ /* clip the region between (640x480) and (1920x1080) */
+ if (vscr->width < min_width)
+ vscr->width = min_width;
+ if (vscr->width > max_width)
+ vscr->width = max_width;
+ if (vscr->height < min_height)
+ vscr->height = min_height;
+ if (vscr->height > max_height)
+ vscr->height = max_height;
+ } else {
+ /* the default window(1280x720) is created with undefined pos
+ * when no geometry info is passed
+ */
+ vscr->org_x = 0xFFFF;
+ vscr->org_y = 0xFFFF;
+ vscr->width = VDPY_DEFAULT_WIDTH;
+ vscr->height = VDPY_DEFAULT_HEIGHT;
+ }
+
+ win_flags = SDL_WINDOW_OPENGL |
+ SDL_WINDOW_ALWAYS_ON_TOP |
+ SDL_WINDOW_SHOWN;
+ if (vscr->is_fullscreen) {
+ win_flags |= SDL_WINDOW_FULLSCREEN_DESKTOP;
+ }
+ vscr->win = NULL;
+ vscr->renderer = NULL;
+ vscr->img = NULL;
+ vscr->org_x = vscr->pscreen_rect.x;
+ vscr->org_y = vscr->pscreen_rect.y;
+ vscr->win = SDL_CreateWindow("ACRN_DM",
+ vscr->org_x, vscr->org_y,
+ vscr->width, vscr->height,
win_flags);
- if (vdpy.dpy_win == NULL) {
- pr_err("Failed to Create SDL_Window\n");
- goto sdl_fail;
- }
- pr_info("SDL display bind to screen %d: [%d,%d,%d,%d].\n", vdpy.pscreen_id,
- vdpy.org_x, vdpy.org_y, vdpy.width, vdpy.height);
+ if (vscr->win == NULL) {
+ pr_err("Failed to Create SDL_Window\n");
+ goto sdl_fail;
+ }
+ pr_info("SDL display bind to screen %d: [%d,%d,%d,%d].\n", vscr->pscreen_id,
+ vscr->org_x, vscr->org_y, vscr->width, vscr->height);
- vdpy.dpy_renderer = SDL_CreateRenderer(vdpy.dpy_win, -1, 0);
- if (vdpy.dpy_renderer == NULL) {
- pr_err("Failed to Create GL_Renderer \n");
- goto sdl_fail;
+ vscr->renderer = SDL_CreateRenderer(vscr->win, -1, 0);
+ if (vscr->renderer == NULL) {
+ pr_err("Failed to Create GL_Renderer \n");
+ goto sdl_fail;
+ }
+ clock_gettime(CLOCK_MONOTONIC, &vscr->last_time);
}
sdl_gl_display_init();
pthread_mutex_init(&vdpy.vdisplay_mutex, NULL);
@@ -971,7 +1073,6 @@ vdpy_sdl_display_thread(void *data)
vdpy.ui_timer_bh.task_cb = vdpy_sdl_ui_refresh;
vdpy.ui_timer_bh.data = &vdpy;
- clock_gettime(CLOCK_MONOTONIC, &vdpy.last_time);
vdpy.ui_timer.clockid = CLOCK_MONOTONIC;
acrn_timer_init(&vdpy.ui_timer, vdpy_sdl_ui_timer, &vdpy);
ui_timer_spec.it_interval.tv_sec = 0;
@@ -1019,34 +1120,48 @@ vdpy_sdl_display_thread(void *data)
/* SDL display_thread will exit because of DM request */
pthread_mutex_destroy(&vdpy.vdisplay_mutex);
pthread_cond_destroy(&vdpy.vdisplay_signal);
- if (vdpy.dpy_img) {
- pixman_image_unref(vdpy.dpy_img);
- vdpy.dpy_img = NULL;
- }
- /* Continue to thread cleanup */
- if (vdpy.dpy_texture) {
- SDL_DestroyTexture(vdpy.dpy_texture);
- vdpy.dpy_texture = NULL;
- }
- if (vdpy.cursor_tex) {
- SDL_DestroyTexture(vdpy.cursor_tex);
- vdpy.cursor_tex = NULL;
- }
+ for (i = 0; i < vdpy.vscrs_num; i++) {
+ vscr = vdpy.vscrs + i;
+ if (vscr == NULL) {
+ continue;
+ }
- if (vdpy.egl_dmabuf_supported && (vdpy.cur_egl_img != EGL_NO_IMAGE_KHR))
- vdpy.gl_ops.eglDestroyImageKHR(vdpy.eglDisplay,
- vdpy.cur_egl_img);
+ if (vscr->img) {
+ pixman_image_unref(vscr->img);
+ vscr->img = NULL;
+ }
+ /* Continue to thread cleanup */
-sdl_fail:
+ if (vscr->surf_tex) {
+ SDL_DestroyTexture(vscr->surf_tex);
+ vscr->surf_tex = NULL;
+ }
+ if (vscr->cur_tex) {
+ SDL_DestroyTexture(vscr->cur_tex);
+ vscr->cur_tex = NULL;
+ }
- if (vdpy.dpy_renderer) {
- SDL_DestroyRenderer(vdpy.dpy_renderer);
- vdpy.dpy_renderer = NULL;
+ if (vdpy.egl_dmabuf_supported && (vscr->egl_img != EGL_NO_IMAGE_KHR))
+ vdpy.gl_ops.eglDestroyImageKHR(vdpy.eglDisplay,
+ vscr->egl_img);
}
- if (vdpy.dpy_win) {
- SDL_DestroyWindow(vdpy.dpy_win);
- vdpy.dpy_win = NULL;
+
+sdl_fail:
+ for (i = 0; i < vdpy.vscrs_num; i++) {
+ vscr = vdpy.vscrs + i;
+ if (vscr == NULL) {
+ continue;
+ }
+
+ if (vscr->renderer) {
+ SDL_DestroyRenderer(vscr->renderer);
+ vscr->renderer = NULL;
+ }
+ if (vscr->win) {
+ SDL_DestroyWindow(vscr->win);
+ vscr->win = NULL;
+ }
}
/* This is used to workaround the TLS issue of libEGL + libGLdispatch
@@ -1113,7 +1228,7 @@ vdpy_init(int *supported_wins)
vdpy.s.n_connect++;
if (supported_wins)
- *supported_wins = 1;
+ *supported_wins = vdpy.vscrs_num;
return vdpy.s.n_connect;
}
@@ -1146,6 +1261,8 @@ int
gfx_ui_init()
{
SDL_SysWMinfo info;
+ struct vscreen *vscr;
+ int i;
setenv("SDL_VIDEO_X11_FORCE_EGL", "1", 1);
setenv("SDL_OPENGL_ES_DRIVER", "1", 1);
@@ -1157,14 +1274,17 @@ gfx_ui_init()
return -1;
}
- SDL_GetDisplayBounds(vdpy.pscreen_id, &vdpy.pscreen_rect);
+ for (i = 0; i < vdpy.vscrs_num; i++) {
+ vscr = vdpy.vscrs + i;
+ SDL_GetDisplayBounds(vscr->pscreen_id, &vscr->pscreen_rect);
- if (vdpy.pscreen_rect.w < VDPY_MIN_WIDTH ||
- vdpy.pscreen_rect.h < VDPY_MIN_HEIGHT) {
- pr_err("Too small resolutions. Please check the "
- " graphics system\n");
- SDL_Quit();
- return -1;
+ if (vscr->pscreen_rect.w < VDPY_MIN_WIDTH ||
+ vscr->pscreen_rect.h < VDPY_MIN_HEIGHT) {
+ pr_err("Too small resolutions. Please check the "
+ " graphics system\n");
+ SDL_Quit();
+ return -1;
+ }
}
SDL_SetHint(SDL_HINT_GRAB_KEYBOARD, "1");
@@ -1196,6 +1316,7 @@ gfx_ui_deinit()
return;
}
+ free(vdpy.vscrs);
SDL_Quit();
pr_info("SDL_Quit\r\n");
}
@@ -1204,35 +1325,41 @@ int vdpy_parse_cmd_option(const char *opts)
{
char *str;
int snum, error;
+ struct vscreen *vscr;
Can this split into another patch?
That is to say: This patch still assumes that it only support one vscreen. And another patches tries to parse the correct number and vscreen info.

error = 0;
+ vdpy.vscrs = calloc(VSCREEN_MAX_NUM, sizeof(struct vscreen));
+ vdpy.vscrs_num = 0;
str = strcasestr(opts, "geometry=");
+ vscr = vdpy.vscrs + vdpy.vscrs_num;
if (opts && strcasestr(opts, "geometry=fullscreen")) {
- snum = sscanf(str, "geometry=fullscreen:%d", &vdpy.pscreen_id);
+ snum = sscanf(str, "geometry=fullscreen:%d", &vscr->pscreen_id);
if (snum != 1) {
- vdpy.pscreen_id = 0;
+ vscr->pscreen_id = 0;
}
- vdpy.width = VDPY_MAX_WIDTH;
- vdpy.height = VDPY_MAX_HEIGHT;
- vdpy.s.is_fullscreen = true;
+ vscr->width = VDPY_MAX_WIDTH;
+ vscr->height = VDPY_MAX_HEIGHT;
+ vscr->is_fullscreen = true;
+ vdpy.vscrs_num++;
pr_info("virtual display: fullscreen.\n");
} else if (opts && strcasestr(opts, "geometry=")) {
snum = sscanf(str, "geometry=%dx%d+%d+%d",
- &vdpy.width, &vdpy.height,
- &vdpy.org_x, &vdpy.org_y);
+ &vscr->width, &vscr->height,
+ &vscr->org_x, &vscr->org_y);
if (snum != 4) {
pr_err("incorrect geometry option. Should be"
" WxH+x+y\n");
error = -1;
}
- vdpy.s.is_fullscreen = false;
+ vscr->is_fullscreen = false;
+ vdpy.vscrs_num++;
pr_info("virtual display: windowed.\n");
}
- vdpy.info.xoff = 0;
- vdpy.info.yoff = 0;
- vdpy.info.width = vdpy.width;
- vdpy.info.height = vdpy.height;
+ vscr->info.xoff = 0;
+ vscr->info.yoff = 0;
+ vscr->info.width = vdpy.vscrs->width;
+ vscr->info.height = vdpy.vscrs->height;
return error;
}


Re: [PATCH 8/8] ACRN:DM:VGPU: Return the parsed scanout_num to virtio_gpu in Guest_VM

Zhao, Yakui
 

On 2022/8/8 15:37, Sun, Peng wrote:
On Mon, 2022-08-08 at 14:13 +0800, Zhao, Yakui wrote:
Return the parsed scanout_num to guest_vm so that the guest_vm can
configure multi-display.

Signed-off-by: Zhao Yakui <yakui.zhao@...>
---
 devicemodel/hw/pci/virtio/virtio_gpu.c | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/devicemodel/hw/pci/virtio/virtio_gpu.c
b/devicemodel/hw/pci/virtio/virtio_gpu.c
index 42d07e053..3601a10b3 100644
--- a/devicemodel/hw/pci/virtio/virtio_gpu.c
+++ b/devicemodel/hw/pci/virtio/virtio_gpu.c
@@ -1619,11 +1619,11 @@ virtio_gpu_init(struct vmctx *ctx, struct
pci_vdev *dev, char *opts)
                        BACKEND_VBSU);
        gpu->scanout_num = 1;
-       gpu->vdpy_handle = vdpy_init(NULL);
+       gpu->vdpy_handle = vdpy_init(&gpu->scanout_num);
[Sun, Peng] I think it is better 2/8 and 8/8 should be combinded as one
patch.
The patch 2 is about API change.
The patch 8 is to query the correct num and notify the vm that the returned scanout_num is used.

        gpu->base.mtx = &gpu->mtx;
        gpu->base.device_caps = VIRTIO_GPU_S_HOSTCAPS;
-       if (gpu->scanout_num < 0) {
+       if ((gpu->scanout_num < 0) || (gpu->scanout_num > 2)) {
                pr_err("%s: return incorrect scanout num %d\n", gpu-
scanout_num);
                return -1;
        }
@@ -1685,7 +1685,7 @@ virtio_gpu_init(struct vmctx *ctx, struct
pci_vdev *dev, char *opts)
        /* prepare the config space */
        gpu->cfg.events_read = 0;
        gpu->cfg.events_clear = 0;
-       gpu->cfg.num_scanouts = 1;
+       gpu->cfg.num_scanouts = gpu->scanout_num;
        gpu->cfg.num_capsets = 0;
        /* config the device id and vendor id according to spec */


Re: [PATCH 7/8] ACRN:DM:VGPU: Calibrate the offset in dmabuf/pixman_image to display the scanout_window

Zhao, Yakui
 

On 2022/8/8 15:34, Sun, Peng wrote:
On Mon, 2022-08-08 at 14:13 +0800, Zhao, Yakui wrote:
Sometimes the virtio_gpu in guest_vm doesn't pass the zero coord_x/y
for the
displayed framebuffer. In such case the offset should be calibrated
for pixman_image/dmabuf
so that it can display the image from the correct image.

Signed-off-by: Zhao Yakui <yakui.zhao@...>
---
 devicemodel/hw/pci/virtio/virtio_gpu.c | 2 ++
 devicemodel/hw/vdisplay_sdl.c          | 2 +-
 devicemodel/include/vdisplay.h         | 1 +
 3 files changed, 4 insertions(+), 1 deletion(-)

diff --git a/devicemodel/hw/pci/virtio/virtio_gpu.c
b/devicemodel/hw/pci/virtio/virtio_gpu.c
index 81ea82889..42d07e053 100644
--- a/devicemodel/hw/pci/virtio/virtio_gpu.c
+++ b/devicemodel/hw/pci/virtio/virtio_gpu.c
@@ -881,6 +881,7 @@ virtio_gpu_cmd_set_scanout(struct
virtio_gpu_command *cmd)
                surf.stride = pixman_image_get_stride(r2d->image);
                surf.surf_format = r2d->format;
                surf.surf_type = SURFACE_PIXMAN;
+               surf.pixel += 4 * (surf.x + surf.y * surf.stride);
[Sun, Peng] I think we should use bpp instead of hard code to 4, in
case the surf_format is not ARGB.
In fact based on the virtio-gpu spec, now it only supports the format of ARGB or ABGR.

Of course it is fine to use the bpp instead of 4 in next version.

                vdpy_surface_set(gpu->vdpy_handle, req.scanout_id,
&surf);
                pixman_image_unref(r2d->image);
                resp.type = VIRTIO_GPU_RESP_OK_NODATA;
@@ -1298,6 +1299,7 @@ virtio_gpu_cmd_set_scanout_blob(struct
virtio_gpu_command *cmd)
        surf.stride = req.strides[0];
        surf.dma_info.dmabuf_fd = r2d->dma_info->dmabuf_fd;
        surf.surf_type = SURFACE_DMABUF;
+       surf.dma_info.dmabuf_offset = req.offsets[0] + 4 * (surf.x +
surf.y * surf.stride);
[Sun, Peng] I think we should use bpp instead of hard code to 4, in
case the surf_format is not ARGB.
        switch (req.format) {
        case VIRTIO_GPU_FORMAT_B8G8R8X8_UNORM:
                drm_fourcc = DRM_FORMAT_XRGB8888;
diff --git a/devicemodel/hw/vdisplay_sdl.c
b/devicemodel/hw/vdisplay_sdl.c
index 65fd78d93..12140d6be 100644
--- a/devicemodel/hw/vdisplay_sdl.c
+++ b/devicemodel/hw/vdisplay_sdl.c
@@ -700,7 +700,7 @@ vdpy_surface_set(int handle, int scanout_id,
struct surface *surf)
                attrs[i++] = EGL_DMA_BUF_PLANE0_PITCH_EXT;
                attrs[i++] = surf->stride;
                attrs[i++] = EGL_DMA_BUF_PLANE0_OFFSET_EXT;
-               attrs[i++] = 0;
+               attrs[i++] = surf->dma_info.dmabuf_offset;
                attrs[i++] = EGL_NONE;
                egl_img = gl_ops->eglCreateImageKHR(vdpy.eglDisplay,
diff --git a/devicemodel/include/vdisplay.h
b/devicemodel/include/vdisplay.h
index c1214a461..e24a4c625 100644
--- a/devicemodel/include/vdisplay.h
+++ b/devicemodel/include/vdisplay.h
@@ -67,6 +67,7 @@ struct surface {
        struct  {
                int dmabuf_fd;
                uint32_t surf_fourcc;
+               uint32_t dmabuf_offset;
        } dma_info;
 };


Re: [PATCH 6/8] ACRN:DM:VGPU: virtio-gpu-flush cmds check whether one scanout_win needs to be displayed

Zhao, Yakui
 

On 2022/8/8 15:28, Sun Peng wrote:
On Mon, 2022-08-08 at 14:13 +0800, Zhao, Yakui wrote:
The virtio-gpu display will be handled by the below cmd sequence:
1. Virtio_GPU_CMD_CREATE_RESOURCE
2. VIRTIO_GPU_CMD_SET_SCANOUT/SET_SCANOUT_BLOB
3. VIRTIO_GPU_CMD_FLUSH

The virtio_gpu_cmd_flush doesn't pass the scanout info.Instead it
only passes the
flushed_region and the resouce_id. So it needs to check whether the
scanout_region
is covered by the flushed_region and then decide whether the
scanout_win needs
to be displayed.

Signed-off-by: Zhao Yakui <yakui.zhao@...>
---
 devicemodel/hw/pci/virtio/virtio_gpu.c | 80 +++++++++++++++++++++---
--
 1 file changed, 67 insertions(+), 13 deletions(-)

diff --git a/devicemodel/hw/pci/virtio/virtio_gpu.c
b/devicemodel/hw/pci/virtio/virtio_gpu.c
index f33809eee..81ea82889 100644
--- a/devicemodel/hw/pci/virtio/virtio_gpu.c
+++ b/devicemodel/hw/pci/virtio/virtio_gpu.c
@@ -975,6 +975,46 @@ virtio_gpu_cmd_transfer_to_host_2d(struct
virtio_gpu_command *cmd)
        memcpy(cmd->iov[1].iov_base, &resp, sizeof(resp));
 }
+static bool
+virtio_gpu_scanout_needs_flush(struct virtio_gpu *gpu,
+                             int scanout_id,
+                             int resource_id,
+                             struct virtio_gpu_rect *flush_rect)
+{
+       struct virtio_gpu_scanout *gpu_scanout;
+       pixman_region16_t flush_region, final_region, scanout_region;
+
+       /* the scanout_id is already checked. So it is ignored in
this function */
+       gpu_scanout = gpu->gpu_scanouts + scanout_id;
+
+       /* if the different resource_id is used, flush can be skipped
*/
+       if (resource_id != gpu_scanout->resource_id)
+               return false;
+
+       pixman_region_init(&final_region);
+       pixman_region_init_rect(&scanout_region,
+                               gpu_scanout->scanout_rect.x,
+                               gpu_scanout->scanout_rect.y,
+                               gpu_scanout->scanout_rect.width,
+                               gpu_scanout->scanout_rect.height);
+       pixman_region_init_rect(&flush_region,
+                               flush_rect->x, flush_rect->y,
+                               flush_rect->width, flush_rect-
height);
+
+       /* Check intersect region to determine whether scanout_region
+        * needs to be flushed.
+        */
+       pixman_region_intersect(&final_region, &scanout_region,
&flush_region);
+
+       /* if intersection_region is empty, it means that the
scanout_region is not
+        * covered by the flushed_region. And it is unnecessary to
update
+        */
+       if (pixman_region_not_empty(&final_region))
+               return true;
+       else
+               return false;
+}
+
 static void
 virtio_gpu_cmd_resource_flush(struct virtio_gpu_command *cmd)
 {
@@ -983,6 +1023,8 @@ virtio_gpu_cmd_resource_flush(struct
virtio_gpu_command *cmd)
        struct virtio_gpu_resource_2d *r2d;
        struct surface surf;
        struct virtio_gpu *gpu;
+       int i;
+       struct virtio_gpu_scanout *gpu_scanout;
        gpu = cmd->gpu;
        memcpy(&req, cmd->iov[0].iov_base, sizeof(req));
@@ -999,24 +1041,36 @@ virtio_gpu_cmd_resource_flush(struct
virtio_gpu_command *cmd)
        }
        if (r2d->blob) {
                virtio_gpu_dmabuf_ref(r2d->dma_info);
-               surf.dma_info.dmabuf_fd = r2d->dma_info->dmabuf_fd;
-               surf.surf_type = SURFACE_DMABUF;
-               vdpy_surface_update(gpu->vdpy_handle, 0, &surf);
+               for (i = 0; i < gpu->scanout_num; i++) {
+                       if (!virtio_gpu_scanout_needs_flush(gpu, i,
req.resource_id, &req.r))
+                               continue;
+
+                       surf.dma_info.dmabuf_fd = r2d->dma_info-
dmabuf_fd;
+                       surf.surf_type = SURFACE_DMABUF;
+                       vdpy_surface_update(gpu->vdpy_handle, i,
&surf);
+               }
+               virtio_gpu_dmabuf_unref(r2d->dma_info);
                resp.type = VIRTIO_GPU_RESP_OK_NODATA;
                memcpy(cmd->iov[1].iov_base, &resp, sizeof(resp));
-               virtio_gpu_dmabuf_unref(r2d->dma_info);
                return;
        }
        pixman_image_ref(r2d->image);
-       surf.pixel = pixman_image_get_data(r2d->image);
-       surf.x = req.r.x;
-       surf.y = req.r.y;
-       surf.width = r2d->width;
-       surf.height = r2d->height;
-       surf.stride = pixman_image_get_stride(r2d->image);
-       surf.surf_format = r2d->format;
-       surf.surf_type = SURFACE_PIXMAN;
-       vdpy_surface_update(gpu->vdpy_handle, 0, &surf);
+       for (i = 0; i < gpu->scanout_num; i++) {
+               if (!virtio_gpu_scanout_needs_flush(gpu, i,
req.resource_id, &req.r))
+                       continue;
+
+               gpu_scanout = gpu->gpu_scanouts + i;
+               surf.pixel = pixman_image_get_data(r2d->image);
+               surf.x = gpu_scanout->scanout_rect.x;
+               surf.y = gpu_scanout->scanout_rect.y;
+               surf.width = gpu_scanout->scanout_rect.width;
+               surf.height = gpu_scanout->scanout_rect.height;
+               surf.stride = pixman_image_get_stride(r2d->image);
+               surf.surf_format = r2d->format;
+               surf.surf_type = SURFACE_PIXMAN;
+               surf.pixel += 4 * (surf.x + surf.y * surf.stride);
[Sun Peng] I thnk we should use bpp, not hard code to 4 in case the
surface format is not ARGB.
Sure. It will be fixed.


+               vdpy_surface_update(gpu->vdpy_handle, i, &surf);
+       }
        pixman_image_unref(r2d->image);
        cmd->iolen = sizeof(resp);