[时间:2017-05] [状态:Open]

[关键词:sdl2,屏幕分辨率,显示区域,多媒体渲染,窗口,sdl2源码分析]

0 引言

本文的主要目标在于使用SDL2获得屏幕相关的属性,比如分辨率、屏幕个数以及屏幕可用区域的范围。

通常情况下,有过图形界面编程经验的人都知道桌面系统的构成,屏幕分辨率是指的整个屏幕区域的宽高,而通常屏幕区域有一些系统的任务栏或者菜单栏;举个例子,windows下的任务栏一般位于下面,并且通常非全屏窗口是不能占用任务栏的。

1 获得屏幕个数

SDL2中提供了获得屏幕个数的接口SDL_GetNumVideoDisplays,具体建议参考sdl2-wiki

当然屏幕还有其他属性,比如显示模式等,可以通过SDL_GetNumDisplayModesSDL_GetDisplayMode获得SDL_DisplayMode的结构,其中包括显示格式(YUV、RGB等)、宽高、刷新率等。

2 每个屏幕的分辨率

SDL_GetDisplayBounds可以获得指定屏幕的显示区域,可以通过显示区域获取屏幕分辨率。

3 获取实际显示区域的大小

SDL_GetDisplayUsableBounds返回的是实际可用显示区域的大小,这个通常比屏幕分辨率小。

4 SDL2内部实现的原理分析

这里以SDL_GetDisplayBounds为例说明,如果读者对其他函数感兴趣,可以查看sdl2代码。

int SDL_GetDisplayBounds(int displayIndex, SDL_Rect * rect)
{
CHECK_DISPLAY_INDEX(displayIndex, -1); if (rect) {
SDL_VideoDisplay *display = &_this->displays[displayIndex]; if (_this->GetDisplayBounds) {
if (_this->GetDisplayBounds(_this, display, rect) == 0) {
return 0;
}
} /* Assume that the displays are left to right */
if (displayIndex == 0) {
rect->x = 0;
rect->y = 0;
} else {
SDL_GetDisplayBounds(displayIndex-1, rect);
rect->x += rect->w;
}
rect->w = display->current_mode.w;
rect->h = display->current_mode.h;
}
return 0; /* !!! FIXME: should this be an error if (rect==NULL) ? */
}

很明显这个函数直接调用了SDL_VideoDevice->GetDisplayBounds函数,那么我们找一个实现版本看看,比如windows下的,代码如下:

static SDL_VideoDevice * WIN_CreateDevice(int devindex)
{
// ...
device->GetDisplayBounds = WIN_GetDisplayBounds;
// ...
}

这个实现被重定向到WIN_GetDisplayBounds函数中,代码如下:

int
WIN_GetDisplayBounds(_THIS, SDL_VideoDisplay * display, SDL_Rect * rect)
{
SDL_DisplayModeData *data = (SDL_DisplayModeData *) display->current_mode.driverdata; rect->x = (int)SDL_ceil(data->DeviceMode.dmPosition.x * data->ScaleX);
rect->y = (int)SDL_ceil(data->DeviceMode.dmPosition.y * data->ScaleY);
rect->w = (int)SDL_ceil(data->DeviceMode.dmPelsWidth * data->ScaleX);
rect->h = (int)SDL_ceil(data->DeviceMode.dmPelsHeight * data->ScaleY); return 0;
}

实现比较简单,直接从display->current_mode中获得数据。那么这个mode在哪里赋值的呢?

在SDL_windowsvideo.c中查找下,发下如下调用:

static SDL_bool WIN_AddDisplay(_THIS, LPTSTR DeviceName)
{
SDL_VideoDisplay display;
SDL_DisplayData *displaydata;
SDL_DisplayMode mode;
DISPLAY_DEVICE device; if (!WIN_GetDisplayMode(_this, DeviceName, ENUM_CURRENT_SETTINGS, &mode)) {
return SDL_FALSE;
} displaydata = (SDL_DisplayData *) SDL_malloc(sizeof(*displaydata));
if (!displaydata) {
return SDL_FALSE;
}
SDL_memcpy(displaydata->DeviceName, DeviceName,
sizeof(displaydata->DeviceName)); SDL_zero(display);
device.cb = sizeof(device);
if (EnumDisplayDevices(DeviceName, 0, &device, 0)) {
display.name = WIN_StringToUTF8(device.DeviceString);
}
display.desktop_mode = mode;
display.current_mode = mode;
display.driverdata = displaydata;
SDL_AddVideoDisplay(&display);
SDL_free(display.name);
return SDL_TRUE;
}

明显这是从EnumDisplayDevices中获取。

至此所有实现逻辑基本理清。

5 小结

本文主要整理我近期遇到的SDL2关于窗口和屏幕属性获取的逻辑,同时分析了SDL_GetDisplayBounds在windows上的实现逻辑。

SDL获得屏幕属性及实现分析的更多相关文章

  1. AbstractBeanDefinition:lenientConstructorResolution属性源码分析

    版本:spring-framework-4.1 一概述 在看AbstractBeanDefinition源码时,注意到lenientConstructorResolution属性有诸多不疑,现在通过示 ...

  2. div层调整zindex属性无效原因分析及解决方法

    在做的过程中,发现了一个很简单却又很多人应该碰到的问题,设置Z-INDEX属性无效.在CSS中,只能通过代码改变层级,这个属性就是z- index,要让z-index起作用有个小小前提,就是元素的po ...

  3. 【转载】div层调整zindex属性无效原因分析及解决方法

    在做的过程中,发现了一个很简单却又很多人应该碰到的问题,设置Z-INDEX属性无效.在CSS中,只能通过代码改变层级,这个属性就是z-index,要让z-index起作用有个小小前提,就是元素的pos ...

  4. img标签和 background 属性的使用分析

    在网页布局中引入图片,最常用的两个就是 img 标签和 background 属性了.但何时使用 img 标签,何时使用 backround 背景图像呢? <img> 标签定义 HTML ...

  5. css属性书写顺序分析

    我们直接从例子出发 @font-face { font-family: 'icomoon'; src: url('fonts/icomoon.eot?speta9'); src: url('fonts ...

  6. 【Web前端】div层调整zindex属性无效原因分析及解决方法

    在做的过程中,发现了一个很简单却又很多人应该碰到的问题,设置Z-INDEX属性无效.在CSS中,只能通过代码改变层级,这个属性就是z- index,要让z-index起作用有个小小前提,就是元素的po ...

  7. 温故vue对vue计算属性computed的分析

    vue 复习笔记(1)一段时间没有看过vue的官方文档了,温故而知新,所以我决定将vue的文档在看一遍 1计算属性computed在vue的computed中声明的是计算属性,可以使用箭头函数来进行定 ...

  8. jQuery中样式和属性模块简单分析

    1.行内样式操作 目标:扩展框架实现行内样式的增删改查 1.1 创建 css 方法 目标:实现单个样式或者多个样式的操作 1.1.1 css方法 -获取样式 注意:使用 style 属性只能获取行内样 ...

  9. LinearLayout-layout_gravity 属性没有效果分析

    今天在一个布局文件中,遇到了一个问题,先看代码 <LinearLayout android:layout_width="match_parent" android:layou ...

随机推荐

  1. PyQt5初级教程(一)

    python 版qt入门级使用说明 我使用的是python3.5安装PyQt5: pip3 install PyQt5 可以用如下代码测试环境是否安装成功,运行成功会弹出一个窗口: from PyQt ...

  2. Python Django 学习 (一) 【Django 框架初探】

    1. 简介: Python下有许多款不同的 Web 框架.Django是重量级选手中最有代表性的一位.2008年9月发布第一个版本,目前的Django版本应该是2.1. 2. 本文的环境 OS : W ...

  3. 条件随机场之CRF++源码详解-特征

    我在学习条件随机场的时候经常有这样的疑问,crf预测当前节点label如何利用其他节点的信息.crf的训练样本与其他的分类器有什么不同.crf的公式中特征函数是什么以及这些特征函数是如何表示的.在这一 ...

  4. cordova 5.4版本 适配全面屏 底部黑边问题

    在全面屏发布之后,Android官方提供了适配方案,即提高App所支持的最大屏幕纵横比,实现很简单,在AndroidManifest.xml中可做如下配置: 更改android.max_aspect值 ...

  5. COGS.1822.[AHOI2013]作业(莫队 树状数组/分块)

    题目链接: COGS.BZOJ3236 Upd: 树状数组实现的是单点加 区间求和,采用值域分块可以\(O(1)\)修改\(O(sqrt(n))\)查询.同BZOJ3809. 莫队为\(O(n^{1. ...

  6. 20172302 《Java软件结构与数据结构》第八周学习总结

    2018年学习总结博客总目录:第一周 第二周 第三周 第四周 第五周 第六周 第七周 第八周 教材学习内容总结 第十二章 优先队列与堆 1.堆(heap)是具有两个附加属性的一棵二叉树: (1)它是一 ...

  7. Linux学习笔记12—磁盘管理

    一.查看磁盘或目录的容量 1.  df命令 作用:查看已挂载磁盘的总容量.使用容量.剩余容量等,可以不加任何参数,默认是按k为单位显示的 参数: -I : 查看inodes使用状况 -h: 使用合适的 ...

  8. 用vue的自定义组件写了一个拖拽 组件,局部的 只能在自定义元素内的

    简单实现 没有做兼容<!DOCTYPE html> <html lang="en"> <head> <meta charset=" ...

  9. 偷懒啦!button多了,这样写既简洁又高效

    在日常的项目中,我最喜欢用button了,但是button多了,写起来又枯燥又费时,今天学到一方法,绝对简单高效! 看看以前: 看吧,这还只是声明,接下来还有: 等等……,是不是很麻烦?现在找到新方法 ...

  10. C#编程(七十五)----------C#使用指针

    原文链接: http://blog.csdn.net/shanyongxu/article/details/47321441 在C#中使用指针的语法 如果想在C#中使用指针,首先对项目进行过配置: 看 ...