现在入手surface pro4 评测是不是有点迟了,等pro5

opengl_qt_simple_draw 本文来讲讲怎样使用 来画平面几何图形,这一节本来是很简单的,因为某些问题都弄 program 238万源代码下载-
&文件名称: opengl_qt_simple_draw
& & & & &&]
&&所属分类:
&&开发工具: C-C++
&&文件大小: 246 KB
&&上传时间:
&&下载次数: 57
&&提 供 者:
&详细说明:本文来讲讲怎样使用opengl来画平面几何图形,这一节本来是很简单的,因为某些问题都弄大半天了。当然,这还是按照NeHe的教程来的学习的。
这次实现的功能是在窗口中画一个三角形,一个矩形,一个圆形。
下面来看看怎么绘制平面几何图形。在设置好需要画的几何图形的属性后,比如颜色信息,就以glBegin()开始,以glEnd()结束,glBegin()中的参数为所画几何图形的类型,比如说GL_ TRIANGLES代表三角形,GL_QUADS为矩形等等。
在glBegin()和glEnd()之间是放的点,这里是三维的点,这些点是对应所画矩形的类型的。
画圆的话稍微麻烦一点,因为opengl中没有直接对应的类型,一般都是采用三角形来逼近,其它很多几何图形也是类似的。在用三角形逼近时,是用的画连续三角形,一般有2种类型。-This article say something about how to use opengl to draw a plane geometry, this section was very simple, because some of the issues Dounong most of the day. Of course, this is in accordance with the NeHe the tutorial come to learn. The functions realized in the window, drawing a triangle, a rectangle, a circle. Let&#39 s take a look at how to draw a plane geometry. After setting up the need to draw geometric properties, such as color, glBegin () to glEnd () end glBegin () in the argument is drawn geometry type, for example, on behalf of the triangle GL_ TRIANGLES GL_QUADS is rectangular, etc.. GlBegin () and glEnd () between the discharge point, here is the three-dimensional points, these points correspond painted rectangular type. Draw a circle, then a little difficult, because opengl not directly correspond to the type of triangle are generally used to approximate many other geometry is similar. Painting with continuous triangle with triangular approximation, generally 2 types.
文件列表(点击判断是否您需要的文件,如果是垃圾请在下面评价投诉):
&&opengl_nehe_02&&..............\glwidget.cpp&&..............\glwidget.h&&..............\glwidget.ui&&..............\main.cpp&&..............\opengl_nehe_02.pro&&..............\opengl_nehe_02.pro.user&&OpenGL_Qt学习笔记之_02(绘制简单平面几何图形).pdf
&近期下载过的用户:
&相关搜索:
&输入关键字,在本站238万海量源码库中尽情搜索:
四棱锥由5个面构成一个封闭的立体图,其中4个共顶点的侧面是三角形,底面是个四边形。如果我们要绘制一个3D的四棱锥只需要绘制这5个面即可,绘制的方法和前一篇文章Opengl_Qt学习笔记之_03(平面图形的着色和旋转)的相同。只不过这里的顶点坐标是3维的,所以图像深度那一维不一定为0。因此我们可以事
&[] - 本次试验的目的很简单,只是显示一个窗口,可以通过F1键值来切换全屏显示和普通屏显示,并当按下ESE键时退出程序。窗口的颜色背景和透视效果(其实该试验都没用上)等用opengl来实现,主要是为后面的学习写了个框架,其实这里主要是重写了3个函数:initializeGL() paintGL() resi
&[] - 在这一节中主要简单介绍下怎样给平面几何着色,以及怎样让绘制出来的几何图形旋转起来。在上一节Opengl_Qt学习笔记之_02(绘制简单平面几何图形) 中已经介绍了如何利用opengl画一些简单的图像,那么这一节就在上面的基础上给它着色,且让他旋转。
&[] - 纹理映射简单的讲,就是把一个纹理(其实说白了,纹理可以理解为一幅图像)映射到空间物体的表面上,因此纹理映射也叫贴图,这个表明不一定是矩形,比如说我可以是球面,或者是任意曲面。在上一篇文章Opengl_Qt学习笔记之_04(3D图形的绘制和旋转)中,我们绘制的空间体的表面都是一些光滑的颜色,如果要在其
&[] - 本次实验主要是学习下opengl中光照的使用方法,opengl中的光照分为环境光,漫射光,镜面光,反射光4种,这里主要是学习环境光和漫射光的设置,同时对比下opengl中支持的几种纹理滤波方式的效果,另外也可以加入色彩融合效果。这次实验是将一个木箱纹理贴到一个立方体上,然后我们在空间屏幕正外方设置了我现在用Qt的QGLWidget,做一个opengl显示图片的界面,但是load图片和显示的过程慢,如果图片多的话,会导致主进程卡住。
我看网上有opengl多线程的方式,我想知道&QGlwidget可以在线程中处理加载和绘制的过程吗?或者模拟多线程来实现?&就是不要让主进程卡住就行了。
回复讨论(解决方案)
@彩阳&来帮帮他
@彩阳&来帮帮他
现在经验显示,多线程只有在载入资源的时候值得使用。渲染时最好不用多线程。
可以开一个线程载入所有资源,然后显示。
不过我做的例子,还没有使用多线程载入和显示纹理。基本的够用。除非你有数十数百个图片,或者一张图片超过了一般电脑分辨率的变态的大小。
简单点用QThread来实现吧。看看相关例子,很容易就实现的。
@彩阳&来帮帮他
现在经验显示,多线程只有在载入资源的时候值得使用。渲染时最好不用多线程。
可以开一个线程载入所有资源,然后显示。
不过我做的例子,还没有使用多线程载入和显示纹理。基本的够用。除非你有数十数百个图片,或者一张图片超过了一般电脑分辨率的变态的大小。
简单点用QThread来实现吧。看看相关例子,很容易就实现的。
我现在就是想载入一些图片,有可能会有几十张(不确定),大小就是分辨率的大小。
我是这么写的:
&&&&&&&&&&QImage&
QStringList&fileList&=&findFiles(QString(&./img&));//拿到图片列表
int&fileNum&=&fileList.size();
glGenTextures(&fileNum,&texture);
for(int&i=0;i&fileNi++)
buf.load(fileList.at(i));
QImage&tex&=&QGLWidget::convertToGLFormat(&buf&);
glTexParameteri(&GL_TEXTURE_2D,&GL_TEXTURE_MIN_FILTER,GL_LINEAR_MIPMAP_NEAREST&);
gluBuild2DMipmaps(&GL_TEXTURE_2D,&GL_RGBA,&tex.width(),tex.height(),&GL_RGBA,&GL_UNSIGNED_BYTE,&tex.bits()&);
但是上边这一段占用的时间挺长的,所以我想把他放在线程中,我就是用的QThread,但是放进去之后,图片就显示不出来的,全是白色的,我理解是最后的两句是绘制的过程,所以不能在线程中实现,但是我该怎么样来实现呢?求指点。
glBindTexture(GL_TEXTURE_2D,&texture[m_pageNum+1]);
glBegin(GL_QUADS);
glTexCoord2f(&0.5,&1.0&);glVertex3f(&0.0,&m_screenScale,&0.0&);
glTexCoord2f(&0.0,&1.0&);glVertex3f(&cos(30*M_PI/180),&m_screenScale,&sin(30*M_PI/180));
glTexCoord2f(&0.0,&0.0&);glVertex3f(&cos(30*M_PI/180),-m_screenScale,sin(30*M_PI/180));
glTexCoord2f(&0.5,&0.0&);glVertex3f(&0.0,&-m_screenScale,&0.0&);
我在真正绘制的时候是这么写的,速度还好。就是最初的载入很慢。
我没有看到在gluBuild2DMipmaps()函数之前调用glBindTexture(GL_TEXTURE_2D,&texture[m_pageNum+1]);&啊。
图片显示不出来,只有白色这种情况,应该是没有绑定纹理(也就是绑定0纹理),而出现白色。
我没有看到在gluBuild2DMipmaps()函数之前调用glBindTexture(GL_TEXTURE_2D,&texture[m_pageNum+1]);&啊。
图片显示不出来,只有白色这种情况,应该是没有绑定纹理(也就是绑定0纹理),而出现白色。
不好意思,是我漏掉了,有写的。
QImage&tex&=&QGLWidget::convertToGLFormat(&buf&);
glBindTexture(&GL_TEXTURE_2D,&texture[i]&);
我就是都在主进程中使用的时候就是好的,图片也都能显示,主窗口就是继承QGLWidget。
因为我是要实时的显示图片,就是从别的窗口切换到这个界面,再去把图片加载进来。但是这一段代码需要的时间挺长,所以会卡住。&我就创建了一个线程,线程里边这么写的:
LoadTexImgThread::LoadTexImgThread()
:QThread()
wglMakeCurrent(hDC,&hRC1);&
LoadTexImgThread::~LoadTexImgThread()
void&LoadTexImgThread::run(&void&)
wglMakeCurrent(hDC,&hRC1);
loadContentTextures();
// wglMakeCurrent(NULL,&NULL);
emit&sigLoadImgFinish();
void&LoadTexImgThread::loadContentTextures()
QStringList&fileList&=&findFiles(QString(&./img&));
int&fileNum&=&fileList.size();
glGenTextures(&fileNum,&texture);
for(int&i=0;i&fileNi++)
bool&falg&=&buf.load(fileList.at(i));
QImage&tex&=&QGLWidget::convertToGLFormat(&buf&);
glBindTexture(&GL_TEXTURE_2D,&texture[i]&);
glTexParameteri(&GL_TEXTURE_2D,&GL_TEXTURE_MIN_FILTER,GL_LINEAR_MIPMAP_NEAREST&);
gluBuild2DMipmaps(&GL_TEXTURE_2D,&GL_RGBA,&tex.width(),tex.height(),&GL_RGBA,&GL_UNSIGNED_BYTE,&tex.bits()&);
// updateGL();
// emit&sigLoadImgFinish();
结果就显示不出来了,在同一个进程中是好的。。
我的QQ是,方便加一下吗?
wglMakeCurrent(hDC,&hRC1);
这几行代码是我在网上找的,说是要设置一下当前CD,但是貌似不起作用,或者是我使用的不对?
这里我说说我对OpenGL开发的理解。
wgl、glx、agl是不同平台下对OpenGL提供的API,在不同平台下和OpenGL&API配合使用。
Qt提供了对OpenGL的封装,并且宣称能够跨平台,因此开发的时候尽量不用平台相关的代码,只用Qt提供的API。
这里我说说我对OpenGL开发的理解。
wgl、glx、agl是不同平台下对OpenGL提供的API,在不同平台下和OpenGL&API配合使用。
Qt提供了对OpenGL的封装,并且宣称能够跨平台,因此开发的时候尽量不用平台相关的代码,只用Qt提供的API。
那几行代码是后加的。&原来没有,就是因为显示不出来,才尝试一下。如果Qt自己能解决那肯定是最好不过了,你有好的方法吗?就针对我这个问题?
Opengl...跨平台,不懂,倒是用过OpenTk
这里我说说我对OpenGL开发的理解。
wgl、glx、agl是不同平台下对OpenGL提供的API,在不同平台下和OpenGL&API配合使用。
Qt提供了对OpenGL的封装,并且宣称能够跨平台,因此开发的时候尽量不用平台相关的代码,只用Qt提供的API。
你可以帮我写一个Qt下边的最简单的代码吗?就是一个线程导入图片,主进程把图片贴到一个矩形上边,可以吗?
我看了一下貌似Qt的opengl没有本来那么麻烦,但是我不知道怎么下手。
这里我说说我对OpenGL开发的理解。
wgl、glx、agl是不同平台下对OpenGL提供的API,在不同平台下和OpenGL&API配合使用。
Qt提供了对OpenGL的封装,并且宣称能够跨平台,因此开发的时候尽量不用平台相关的代码,只用Qt提供的API。
Qt是这么用吗?
GLuint&texture&=&bindTexture(QPixmap(QString(&./layer.png&)),&GL_TEXTURE_2D);
glBegin(GL_QUADS);
QRectF&rect(0.0f,0.0f,0.2f,0.2f);
drawTexture(rect,texture,GL_TEXTURE_2D);
什么也画不出来啊,那个地方不对啊。
没有人会QGLWidget贴纹理吗?
就是完全使用Qt的函数,不要用opengl的方法。
。。。。qglwidget里面不都是直接用gl的东西么。。
Qt有个opengl的教程,&是根据NEHE&openggl改的。可以搜索下,有你需要的。
QtOpengl在Qt4.8以后就开始支持多线程渲染了,在Qt4.8版本中的demos里面有一个例子,glhypnotizer,好像就是用多线程进行渲染的,楼主可以去看一下,还有去google搜一下&qt&opengl&multithreading吧。
借个地方,楼主的问题解决了么?
我也在纠结,我现在是这样的
加载代码:
makeCurrent();
QImage&bgImage&=&convertToGLFormat(m_bg_image);
glGenTextures(1,&&m_bg_texture);
glBindTexture(GL_TEXTURE_2D,&m_bg_texture);
glTexImage2D(GL_TEXTURE_2D,&0,&4,&bgImage.width(),&bgImage.height(),&0,
GL_BGRA,&GL_UNSIGNED_BYTE,&bgImage.bits());
glBindTexture(GL_TEXTURE_2D,&0);
显示代码:
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glDepthMask(false);
QRectF&rect(-0.8f,&-0.8f,&1.0f,&1.0f);
drawTexture(rect,&m_bg_texture);
glDepthMask(true);
不管原来图像里是啥,最终显示都是全白。郁闷。
不知道为什么不显示原来的颜色
好吧,加载改成了这样。
makeCurrent();
QImage&bgImage&=&convertToGLFormat(m_bg_image);&//调整为RGBA,并解决上下颠倒的问题
QPixmap&bgP
bool&su&=&bgPixmap.convertFromImage(bgImage);&//不用QPixmap,显示白的
m_bg_texture&=&bindTexture(bgPixmap);
发现Qt5.3上convertToGLFormat()有bug,文档写&The&GL&format&used&is&GL_RGBA.&,代码里用Format_ARGB32,坑爹!!
还有bindTexture内部会转Format,用了bindTexture也不需要用QPixmap了
QImage&bgImage&=&m_bg_image.transformed(QTransform::fromScale(1.0,&-1.0));&//解决上下颠倒的问题
makeCurrent();&//没验证是不是需要,先放着
m_bg_texture&=&bindTexture(bgImage);8043人阅读
opengl(6)
1. 目的:在Qt中使用Opengl函数绘制一个三角形;
2. 实现如下:
// myQtOpenglWindow.h
#ifndef MYQTOPENGLWINDOW_H
#define MYQTOPENGLWINDOW_H
#include &QtOpenGL/QtOpenGL&
#include &QtOpenGL/QGLWidget&
#include &QWidget&
class myQtOpenglWindow : public QGLWidget
explicit myQtOpenglWindow( QWidget* parent = 0, const char* name = 0, bool fs = false );\
~myQtOpenglWindow();
protected:
void initializeGL();
void paintGL();
void resizeGL( int width, int height );
void keyPressEvent(QKeyEvent *);
protected:
bool fullS
public slots:
#endif // MYQTOPENGLWINDOW_H
// myQtOpenglWindow.cpp
#include &myqtopenglwindow.h&
#include &gl/GLU.h&
myQtOpenglWindow::myQtOpenglWindow( QWidget* parent, const char* name, bool fs )
:QGLWidget( parent )
//保存窗口是否为全屏的状态。
fullScreen =
//设置窗口的位置,即左上角为(0,0)点,大小为640*480。
setGeometry( 0, 0, 640, 480 );
// 设置窗口的标题为“My's OpenGL Framework”。
//setCaption( &My's OpenGL Framework& );
// 如果fullscreen为真,那么就全屏显示这个窗口。
if ( fullScreen )
showFullScreen();
myQtOpenglWindow::~myQtOpenglWindow()
void myQtOpenglWindow::initializeGL()
glShadeModel(GL_SMOOTH);
glClearColor( 0.0, 0.0, 0.0, 0.0 );
glClearDepth( 1.0 );
glEnable( GL_DEPTH_TEST );
glDepthFunc( GL_LEQUAL );
glHint( GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST );
void myQtOpenglWindow::paintGL()
glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
glLoadIdentity();
glTranslatef(-1.5,0.0,-6.0);
glBegin(GL_TRIANGLES);
glVertex3f(0.0,1.0,0.0);
glVertex3f(-1.0,-1.0,0.0);
glVertex3f(1.0,-1.0,0.0);
void myQtOpenglWindow::resizeGL(int width, int height)
//防止height为0
if( height == 0 )
height =1;
//重置当前的视口(Viewport)
glViewport( 0, 0, (GLint)width, (GLint)height );
//选择投影矩阵。
glMatrixMode( GL_PROJECTION );
//重置投影矩阵
glLoadIdentity();
//建立透视投影矩阵
gluPerspective( 45.0, (GLfloat)width/(GLfloat)height, 0.1, 100.0 );
//gluPerspective(45.0,(GLfloat)width() / (GLfloat)height(),0.1,100.0);
// 选择模型观察矩阵
glMatrixMode( GL_MODELVIEW );
// 重置模型观察矩阵。
glLoadIdentity();
void myQtOpenglWindow::keyPressEvent(QKeyEvent * e)
switch ( e-&key() )
//如果按下了F2键,那么屏幕是否全屏的状态就切换一次。然后再根据需要,显示所要的全屏窗口或者
普通窗口。
case Qt::Key_F2:
fullScreen = !fullS
if ( fullScreen )
showFullScreen();
showNormal();
setGeometry( 0, 0, 640, 480 );
updateGL();
//如果按下了Escape键,程序退出。
case Qt::Key_Escape:
myQtOpenglWindow *poglwindow = new myQtOpenglW
poglwindow-&show();
即可显示Opengl窗口,其中有一个三角形
错误解决:
编译时,gluPerspective处如下错误:
  C:\Users\Administrator\Desktop\tornadomeet\opengl\opengl_nehe_01\glwidget.cpp:46: error:&
C3861: “gluPerspective”: 找不到标识符。
很多人在用QT写OpenGL程序的时候需要使用glu开头的函数,但是却发现怎么也没法使用,例如:
gluPerspective函数,用来建立透视投影矩阵的。
其实不仅仅是QT,包括VC编译器,也都会出现上面的问题。
错误:C3861: 'gluPerspective': identifier not found
解决办法:
在pro文件中加入:LIBS += glut.lib glut32.lib
但是前提是你将这两个lib文件放入了qt的bin目录下,我的电脑安装的对应目录是:
C:\QtSDK\Simulator\Qt\mingw\lib
然后在你使用到相应函数中添加头文件:
#include &GL/GLU.h&
这样基本上就可以使用glu开头的函数了。
运行出现下列错误:
myqtopenglwindow.obj : error LNK2019: 无法解析的外部符号 &__declspec(dllimport) public: virtual&
__thiscall QGLWidget::~QGLWidget(void)& (__imp_??1QGLWidget@@UAE@XZ),该符号在函数 &public:&
virtual __thiscall myQtOpenglWindow::~myQtOpenglWindow(void)& (??1myQtOpenglWindow@@UAE@XZ) 中被引
用myqtopenglwindow.obj : error LNK2019: 无法解析的外部符号 &__declspec(dllimport) public: __thiscall&
QGLWidget::QGLWidget(class QWidget *,class QGLWidget const *,class QFlags&enum Qt::WindowType&)&&
(__imp_??0QGLWidget@@QAE@PAVQWidget@@PBV0@V?$QFlags@W4WindowType@Qt@@@@@Z),该符号在函数 &public:&
__thiscall myQtOpenglWindow::myQtOpenglWindow(class QWidget *,char const *,bool)& (??
0myQtOpenglWindow@@QAE@PAVQWidget@@PBD_N@Z) 中被引用
myqtopenglwindow.obj : error LNK2001: 无法解析的外部符号 &protected: virtual bool __thiscall&
QGLWidget::event(class QEvent *)& (?event@QGLWidget@@MAE_NPAVQEvent@@@Z)
myqtopenglwindow.obj : error LNK2001: 无法解析的外部符号 &protected: virtual void __thiscall&
QGLWidget::paintEvent(class QPaintEvent *)& (?paintEvent@QGLWidget@@MAEXPAVQPaintEvent@@@Z)
myqtopenglwindow.obj : error LNK2001: 无法解析的外部符号 &protected: virtual void __thiscall&
QGLWidget::resizeEvent(class QResizeEvent *)& (?resizeEvent@QGLWidget@@MAEXPAVQResizeEvent@@@Z)
myqtopenglwindow.obj : error LNK2001: 无法解析的外部符号 &public: virtual void __thiscall&
QGLWidget::updateGL(void)& (?updateGL@QGLWidget@@UAEXXZ)
myqtopenglwindow.obj : error LNK2001: 无法解析的外部符号 &public: virtual void __thiscall&
QGLWidget::updateOverlayGL(void)& (?updateOverlayGL@QGLWidget@@UAEXXZ)
myqtopenglwindow.obj : error LNK2001: 无法解析的外部符号 &protected: virtual void __thiscall&
QGLWidget::initializeOverlayGL(void)& (?initializeOverlayGL@QGLWidget@@MAEXXZ)
myqtopenglwindow.obj : error LNK2001: 无法解析的外部符号 &protected: virtual void __thiscall&
QGLWidget::resizeOverlayGL(int,int)& (?resizeOverlayGL@QGLWidget@@MAEXHH@Z)
myqtopenglwindow.obj : error LNK2001: 无法解析的外部符号 &protected: virtual void __thiscall&
QGLWidget::paintOverlayGL(void)& (?paintOverlayGL@QGLWidget@@MAEXXZ)
myqtopenglwindow.obj : error LNK2001: 无法解析的外部符号 &protected: virtual void __thiscall&
QGLWidget::glInit(void)& (?glInit@QGLWidget@@MAEXXZ)
myqtopenglwindow.obj : error LNK2001: 无法解析的外部符号 &protected: virtual void __thiscall&
QGLWidget::glDraw(void)& (?glDraw@QGLWidget@@MAEXXZ)
myqtopenglwindow.obj : error LNK2001: 无法解析的外部符号 &public: virtual class QPaintEngine *&
__thiscall QGLWidget::paintEngine(void)const & (?paintEngine@QGLWidget@@UBEPAVQPaintEngine@@XZ)
moc_myqtopenglwindow.obj : error LNK2019: 无法解析的外部符号 &__declspec(dllimport) public:&
virtual void * __thiscall QGLWidget::qt_metacast(char const *)& (__imp_?
qt_metacast@QGLWidget@@UAEPAXPBD@Z),该符号在函数 &public: virtual void * __thiscall&
myQtOpenglWindow::qt_metacast(char const *)& (?qt_metacast@myQtOpenglWindow@@UAEPAXPBD@Z) 中被引用
moc_myqtopenglwindow.obj : error LNK2019: 无法解析的外部符号 &__declspec(dllimport) public:&
virtual int __thiscall QGLWidget::qt_metacall(enum QMetaObject::Call,int,void * *)& (__imp_?
qt_metacall@QGLWidget@@UAEHW4Call@QMetaObject@@HPAPAX@Z),该符号在函数 &public: virtual int&
__thiscall myQtOpenglWindow::qt_metacall(enum QMetaObject::Call,int,void * *)& (?
qt_metacall@myQtOpenglWindow@@UAEHW4Call@QMetaObject@@HPAPAX@Z) 中被引用
moc_myqtopenglwindow.obj : error LNK2001: 无法解析的外部符号 &__declspec(dllimport) public: static&
struct QMetaObject const QGLWidget::staticMetaObject& (__imp_?
staticMetaObject@QGLWidget@@2UQMetaObject@@B)
debug\test.exe : fatal error LNK1120: 16 个无法解析的外部命令
解决方法:
添加外部文件:QT/QT5.3.1/5.3/msvc2010_opengl/lib/Qt5OpenGL.lib,再次试一试,不行,删除debug和
release文件夹,然后清理项目,然后重新构建项目,再次运行,或清理项目后,执行qmake,再次运行试试。
用Qtcreator添加Qt设计师界面类时,用该类声明一个对象,编译有可能出现:Qtcreator中编译出现无法解
析的外部符号,未找到文件:mainwindow.obj类似的错误,解决方法:删除项目目录下的release和dubug文件夹,
然后清理项目,重新构建,执行qmake,参考:/p/
注:执行qmake即可,再重新运行即可。
参考文章:
http://blog.csdn.net/yibulianhua/article/details/7597205
http://blog.csdn.net/alicehyxx/article/details/5251962
/tornadomeet/archive//2651574.html
/tornadomeet/archive//2654327.html
参考知识库
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
访问:343316次
积分:3687
积分:3687
排名:第7335名
原创:93篇
转载:112篇
评论:21条
(1)(8)(6)(6)(1)(17)(1)(4)(10)(30)(50)(10)(7)(3)(5)(19)(16)(9)(1)(4)(2)这里的主机是64位的ACER 5745DG,安装了桌面发行版Fedora20,桌面环境是GNOME。
这里的目标板是CortexA8的AM335x,安装了之前编译好的U-Boot、Kernel和Filesystem,安装的过程见《U-Boot for AM335x》、《为AM335x移植Linux内核主线代码》系列。
Step 1: Install Qt for Master
给主机安装Qt的方法可以非常简单粗暴:
yum install qt5*
yum install qt-creator
当然也可以不使用这样简单粗暴的&全部的通通的安装&的方式,而是选择需要的组件来安装,比如:
yum install qt5-qtbase
yum install qt5-qttools
安装完成之后,文件系统会增加以下的内容:
/usr/bin/qmake-qt5
/usr/bin/qtcreator
/usr/share/qt5/
/usr/share/qtcreator/
/usr/lib64/qt5/
/usr/lib64/qtcreator/
执行一个示例程序试试:
[maria@localhost ~]$ cd /usr/lib64/qt5/examples/quick/demos/clocks/
[maria@localhost lighting]$ ./clocks
NOTE:也可以采用编译源代码的方式来安装。在解压后的源代码目录下执行:
[maria@localhost qt-x86]$ ./configure -opensource -confirm-license -debug -prefix ../../build -platform linux-g++ -v
[maria@localhost qt-x86]# gmake -j8
[maria@localhost qt-x86]# gmake -j8 install
编译过程大概会花两个小时,完成之后运行示例程序,和使用yum来安装的效果是一样的:
[maria@localhost qt]$ cd ../build/examples/quick/demos/clocks/
[maria@localhost lighting]$ ./clocks
NOTE:configure命令中-prefix的&当前目录&为源代码目录下的qtbase。
NOTE:readelf命令可以用来观察可执行文件需要的动态库和装载器,从而知道动态链接的库为什么找不到。
NOTE:ldd命令可以用来观察可执行文件的库依赖。
NOTE:rpm -qf命令可以用来观察库文件所属的软件包。
NOTE: sync将内存缓存的文件强制写入磁盘,使用tftp获取文件之后,需要先执行sync再断电。
Step 2: About SGX
在编译目标板Qt之前,先要理解什么是SGX:
The SGX subsystem is a Texas Instruments instantiation of the POWERVR SGX530 core form Imagination Technologies Ltd.
The 2D/3D graphics accelerator (SGX) subsystem accelerates 2-dimensional (2D) and 3-dimensional (3D) graphics applications. The SGX subsystem is based on the POWERVR SGX core from Imagination Technologies. SGX is a new generation of programmable POWERVR graphic cores. The POWERVR SGX530 v1.2.5 architecture is scalable and can target all market segments from mainstream mobile devices to high-end desktop graphics. Targeted applications include feature phone, PDA, and hand-held games.
TI SOCs例如AM335x,具备3D核心,它能够使用dedicated hardware进行3D加速;而这里的delicated hardware就基于SGX技术;
Graphics cores是用来加速图形的,它并没有video decode功能,视频加速神马的和它没有关系;
视频加速和OpenGL ES1.1 OpenGL ES2.0有关(不推荐使用OpenVG 1.1),它们需要调用SGX驱动;
OpenGL可以做成单独的application,也可以做成Android、Qt、Xrog等的back-end。
SGX core没有包含在ARM核里,但是它的Graphics drivers需要跑在ARM核上(所有的东西都需要跑在ARM核上),怎么办呢?其实Graphics drivers包含有OS specific driver ,它能够将SGX core做内存映射,因此可在ARM core上对图形引擎SGX编程。
到这里为止,是不是弄清楚了SGX、OpenGL、Qt之间的关系了呢?(^ - ^)
首先,移植Qt需要指定它的platform,也就是eglfs、directfb、linuxfb等等;
其次,安装eglfs需要OpenGL图形库;
最后,OpenGL会调用SGX,驱动delicated hardware;
Linux的mainline里面并没有SGX Driver,因为TI公司并没有将其开源。TI公司不开源的代码极少,SGX是其中之一(也许是唯一一个)。
因为SGX的驱动不开源,所以必须要使用TI公司提供的SDK包,将二进制可执行文件打包进内核。
另外,在编译SGX之前,还要先制作编译好的Kernel和目标文件系统,以及为主机安装ssh、ftp、tftp服务。
Step 3: Install SSH, FTP, TFTP Services
为了调试的方便,这里为主机安装SSH、FTP、TFTP服务:
[root@localhost maria]# yum install vsftpd
[root@localhost maria]# yum install ftp
[root@localhost maria]# yum install tftp-server
[root@localhost maria]# yum install tftp
[root@localhost maria]# service sshd start
[root@localhost maria]# service vsftpd start
[root@localhost maria]# service tftp start
网络功能对于嵌入式Linux的调试是非常重要的,正常工作的网络能够大大节省调试的时间。
当然,串口也是非常重要的。
Step 4: Make the Kernel
内核需要修改,是因为Graphics SDK会调用内核的公共函数地址入口,有一些函数是TI提供的内核里面存在,而mainline的内核里面没有的。看起来貌似要修改的地方很多,其实关键只有两个内容:reset_controller和register_vsync_cb。
A. 修改memuconfig中有关reset的内容:
使用make menuconfig命令,使能RESET_CONTROLLER:
CONFIG_RESET_CONTROLLER=y
这一步是必须的,因为PVR服务的pvrsrvkm模块用到了很多reset_control_*函数。
B. 为drivers/reset/core.c文件添加如下内容:
int reset_control_is_reset(struct reset_control *rstc)
if (rstc-&rcdev-&ops-&is_reset)
return rstc-&rcdev-&ops-&is_reset(rstc-&rcdev, rstc-&id);
return -ENOSYS;
EXPORT_SYMBOL_GPL(reset_control_is_reset);
int reset_control_clear_reset(struct reset_control *rstc)
if (rstc-&rcdev-&ops-&clear_reset)
return rstc-&rcdev-&ops-&clear_reset(rstc-&rcdev, rstc-&id);
return -ENOSYS;
EXPORT_SYMBOL_GPL(reset_control_clear_reset);
这两个函数会给Graphics SDK调用,因此需要定义它们。重新编译之后,函数名会内核源代码根目录下的System.map文件中出现。
C. 为include/linux/reset-controller.h文件添加如下内容:
struct reset_control_ops {
int (*reset)(struct reset_controller_dev *rcdev, unsigned long id);
int (*assert)(struct reset_controller_dev *rcdev, unsigned long id);
int (*deassert)(struct reset_controller_dev *rcdev, unsigned long id);
int (*is_reset)(struct reset_controller_dev *rcdev, unsigned long id);
int (*clear_reset)(struct reset_controller_dev *rcdev, unsigned long id);
相应的为 reset_control_ops结构体增加成员变量。
D. 为include/linux/reset.h文件添加如下内容:
int reset_control_reset(struct reset_control *rstc);
int reset_control_assert(struct reset_control *rstc);
int reset_control_deassert(struct reset_control *rstc);
int reset_control_is_reset(struct reset_control *rstc);
int reset_control_clear_reset(struct reset_control *rstc);
相应的为头文件做声明。
E. 为arch/arm/boot/dts/am33xx.dtsi文件添加如下内容:
prcm: prcm@44e00000 {
compatible = &ti,am3-prcm&;
reg = &0x44e0&;
#reset-cells = &1&;
prcm_clocks: clocks {
#address-cells = &1&;
#size-cells = &0&;
prcm_clockdomains: clockdomains {
compatible = &ti,sgx&;
ti,hwmods = &gfx&;
reg = &0xx1000000&;
interrupts = &37&;
resets = &&prcm 0&;
这是devicetree的内容。
如果看不懂dts文件的格式,可以阅读内核文档Documentation/devicetree/booting-without-of.txt 。
F. 添加ti_reset.c文件:
drivers/reset/core.c文件声明了一个结构体struct reset_control,它的定义则由函数of_reset_control_get返回,并且在返回之前给其成员变量struct reset_controller_dev *rcdev赋值。
of_reset_control_get函数被reset_control_get函数调用;reset_control_get函数被SGX的PVRSRVDriverProbe函数调用。
在继续调试之前,先来理解list_for_each:
* list_for_each - iterate over a list
* @pos: the &struct list_head to use as a loop cursor.
* @head: the head for your list.
#define list_for_each(pos, head) \
&&&&&&& for (pos = (head)-& pos != (head); pos = pos-&next)&&&&&&&&&&&&&&&&&&&&& \
&&&&&&&&&&&& pos = list_next_entry(pos, member))
pos是循环变量,相当于for循环里面的i;head是链表list的表头;list_next_entry展开得到:
container_of((pos)-&member.next, typeof(*(pos)), member);
container_of的原型是container_of(ptr, type, member) ,它是一个非常常见的宏定义,含义是,返回type类型的地址,type类型包含了member类型,而ptr是实际的member类型指针。所以list_next_entry的含义是,返回一个typeof(*(pos))的地址,它包含有member这个类型,且(pos)-&member.next指向这个member。
再来理解 list_for_each_entry:
* list_for_each_entry - iterate over list of given type
* @pos: the type * to use as a loop cursor.
* @head: the head for your list.
* @member: the name of the list_struct within the struct.
#define list_for_each_entry(pos, head, member) \
for (pos = list_first_entry(head, typeof(*pos), member); \
&pos-&member != (head); \
pos = list_next_entry(pos, member))
pos是循环变量,相当于for循环里面的i;head是链表list的表头;member是被包含的类型定义;
首先,pos初始化为typeof(*pos)类型的指针,它包含有member类型,且member的地址为head-&next;
然后,如果没有循环返回到head,则pos会指向包含有(pos)-&member.next的pos类型地址。
所以,of_reset_control_get函数中的list_for_each_entry(r, &reset_controller_list, list)含义是:
r相当与for循环里面的i,指向下一个被操作的struct reset_controller_dev;reset_controller_list是链表的表头;
首先,r初始化为struct reset_controller_dev类型的指针,它包含有list类型,且list的地址为(&reset_controller_list)-&next;
但是已知 reset_controller_list在此文件头被初始化了,它是一个空链表:
static LIST_HEAD(reset_controller_list);
因此为了让list_for_each_entry得到有效的执行,即得到可用的rcdev,需要执行reset_controller_register函数。
So,将TI公司提供的内核中的ti_reset.c拷贝到driver/reset目录下,它包含有关键的注册操作,即reset_controller_register函数。
另外,不要忘记修改Makefile和Kconfig。
另外,不要忘记把ti_reset.c中的.compatible值改为和am33xx.dtsi文件中相同的&ti,am3-prcm&。
G. 为drivers/video/fbdev/da8xx-fb.c文件添加如下内容:
static vsync_callback_t vsync_cb_
static void *vsync_cb_
int register_vsync_cb(vsync_callback_t handler, void *arg, int idx)
if ((vsync_cb_handler == NULL) && (vsync_cb_arg == NULL)) {
vsync_cb_arg =
vsync_cb_handler =
return -EEXIST;
EXPORT_SYMBOL(register_vsync_cb);
int unregister_vsync_cb(vsync_callback_t handler, void *arg, int idx)
if ((vsync_cb_handler == handler) && (vsync_cb_arg == arg)) {
vsync_cb_handler = NULL;
vsync_cb_arg = NULL;
return -ENXIO;
EXPORT_SYMBOL(unregister_vsync_cb);
H. 为include/video/da8xx-fb.h文件添加如下内容:
typedef void (*vsync_callback_t)(void *arg);
int register_vsync_cb(vsync_callback_t handler, void *arg, int idx);
int unregister_vsync_cb(vsync_callback_t handler, void *arg, int idx);
是不是觉得内核的修改很复杂呢?其实它的主要功能,就是添加了一个reset_controller的platform设备,并且提供reset和vsync_cb函数供Graphics SDK调用。编译完内核,就可以进行文件系统的制作啦(^_^)
Step 5: Prepare the Filesystem
A. 新建目标文件系统:
[maria@localhost qt]$ mkdir /home/maria/qt/rootfs -p
它相当于目标文件系统的根目录。
B. 编译busybox,将输出拷贝到目标文件系统:
make ARCH=arm CROSS_COMPILE=/opt/i686-arago-linux/usr/bin/arm-linux-gnueabihf- menuconfig
make ARCH=arm CROSS_COMPILE=/opt/i686-arago-linux/usr/bin/arm-linux-gnueabihf- all
make ARCH=arm CROSS_COMPILE=/opt/i686-arago-linux/usr/bin/arm-linux-gnueabihf- install
使用busybox默认配置即可,不用修改它。
之前在《为AM335x移植Linux内核主线代码》系列里,制作busybox的时候使用了静态编译,动态编译无法运行,这是因为动态编译的_install/bin/busybox找不到装载器。
[maria@localhost bin]$ /opt/i686-arago-linux/usr/bin/arm-linux-gnueabihf-ldd --root ../../../rootfs.save busybox
libm.so.6 =& /lib/libm.so.6 (0xdeadbeef)
ld-linux-armhf.so.3 =& /lib/ld-linux-armhf.so.3 (0xdeadbeef)
libc.so.6 =& /lib/libc.so.6 (0xdeadbeef)
解决的方法很简单,就是拷贝正确的装载器和库文件,放置在目标文件系统的正确位置即可,见接下来的步骤。
编译完成之后,将_install目录下的所有内容,拷贝到A步骤创建的rootfs下:
bin linuxrc sbin usr
C. 创建lib目录,拷贝库文件:
在目标文件系统的根目录下,创建lib目录;
一般这些库文件在交叉编译器安装目录下的libc里面,除了busybox需要的三个库文件之外,还有很多其他的库文件;
将这些库文件拷贝到lib目录中;
D. 创建etc目录,编辑需要的内容:
创建rc0.d、rc1.d、rc2.d、rc3.d、rc4.d、rc5.d、rc6.d、rcS.d八个目录;
将SDK开发包提供的文件系统中的etc/group、etc/passwd、etc/shadow三个文件拷贝过来;
将SDK开发包提供的文件系统中的etc/default/rcS文件拷贝过来;
将SDC开发包提供的文件系统中的etc/inittab文件拷贝过来;
将SDC开发包提供的文件系统中的etc/fstab文件拷贝过来;
将SDC开发包提供的文件系统中的etc/init.d/rc、/etc/init.d/rcS文件拷贝过来;
E. 创建dev、home、home/root、media、mnt、opt、proc、sys、var目录:
无需拷贝dev文件,因为内核会生成它们。
将目标文件系统拷贝到SD卡的rootfs分区,然后将SD插入目标板,上电运行,串口终端会出现启动信息,最终出现登陆提示符。这说明,Linux的runlevel 3已经可以正确运行了。
NOTE:将飞凌提供init.sysvinit拷贝到sbin目录下。
NOTE:将飞凌提供的ethtool拷贝到sbin目录下。
NOTE:将Graphics SKD编译出来的devmem2拷贝到sbin目录下。
NOTE:记得在lib下创建modules/3.18.4目录;
NOTE:这里要在rcS文件的倒数第二个非空行添加:
echo &mount -o remount,rw /dev/root&
mount -o remount,rw /dev/root
这样启动的时候就不用手动执行mount命令了。
Step 6: Make the SDK
从TI官网下载最新版的Graphics SDK:
编译Graphics SDK之前,需要编译一次内核,因此Graphics SDK需要调用内核符号表,最好是确保它一直是最新的。
Graphics SDK不会对内核做任何修改,它只会更改目标文件系统。
如果Graphics SDK编译成功,应该能够生成omaplfb.ko、pvrsrvkm.ko、bufferclass_ti.ko三个模块文件,并且它们能够被内核正确加载。omaplfs负责和framebuffer的接口,pvrsrvkm负责和用户层服务的接口, bufferclass_ti负责使用proprietary extension,它允许streaming playback through SGX。除了模块文件外,它还会生成OpenGL ES11/20/VG的二进制可执行文件,供用户的程序调用。
[maria@localhost graphics]$ ./Graphics_SDK_setuplinux_hardfp_5_01_01_02.bin &help
[maria@localhost graphics]$ ./Graphics_SDK_setuplinux_hardfp_5_01_01_02.bin &prefix \
/home/maria/qt/graphics/Graphics_SDK_5_01_01_02
(好像Fedora21只能使用--mode console,--mode standard没有效果,而且使用&es8.x参数会出现error。)
为源代码根目录下的vim Rules.make文件,添加这四个变量(换成自己的实际路径):
SDK_INSTALL_DIR=/home/maria/qt
LINUX_DEVKIT_PATH=/opt/i686-arago-linux/usr
LINUXKERNEL_INSTALL_DIR=$(HOME)/linux-3.18.4-v3
DESTDIR=$(HOME)/rootfs
另外,如果你使用的是Graphics_SDK_5_01_01_01,还需要将GFX_Linux_KM/services4/3rdparty/dc_ti335x_linux/Kbuild文件的EXTRA_CFLAGS修改过来,因为3.18.4的内核将omap2目录放置在了driver/video/fbdev目录下,而不是driver/video目录:
EXTRA_CFLAGS = -DLINUX \
-DCONFIG_OMAP2_DSS \
-I$(PVR_BUILD_DIR)/include4 \
-I$(PVR_BUILD_DIR)/services4/include \
-I$(PVR_BUILD_DIR)/services4/system/$(PVR_SYSTEM) \
-I$(KERNELDIR)/drivers/video/omap2 \
-I$(KERNELDIR)/drivers/video/fbdev/omap2 \
-I$(PVR_BUILD_DIR)/services4/system/include \
$(SYS_CFLAGS.1) \
然后在源代码根目录下执行make命令(注意ARCH必须以环境变量的形式出现):
[maria@localhost Graphics_SDK_5_01_01_02]$ export ARCH=arm
[maria@localhost Graphics_SDK_5_01_01_02]$ make help
[maria@localhost Graphics_SDK_5_01_01_02]$ make CROSS_COMPILE=/opt/i686-arago-linux/usr/bin/arm-linux-gnueabihf- BUILD=debug OMAPES=8.x FBDEV=yes SUPPORT_XORG=0 all
[maria@localhost Graphics_SDK_5_01_01_02]$ make CROSS_COMPILE=/opt/i686-arago-linux/usr/bin/arm-linux-gnueabihf- BUILD=debug OMAPES=8.x FBDEV=yes SUPPORT_XORG=0 install
执行完毕之后,会发现目标文件系统的opt下增加了两个目录(etc目录下也有增加的内容,暂时可不考虑它们)。
将gfxlibraries、gfxsdkdemos这两个目录拷贝到目标文件系统下,将文件系统放置进SD卡,上电启动:
~ # cd /opt/gfxsdkdemos/
/opt/gfxsdkdemos # ./335x-demo
/* 很多的打印信息 */
PVR: High Water Mark = 0 bytes
Loaded PowerVR consumer services.
/opt/gfxsdkdemos # lsmod
omaplfb 12320 0 - Live 0xbf08a000 (O)
omaplfb, Live 0xbf000000 (O)
如果lsmod命令执行的结果如上所示,说明模块被正确的加载,Graphics SDK的驱动部分就制作成功啦。
由上面的调试过程也可以知道,遇到问题的时候不要害怕找不到解决方法,因为阅读README和源代码总是能有非常大的帮助,而且由于Linux本身代码的健壮性,摸索它的脉络是相对容易的,它不会像糟糕的代码那样给人一团乱麻的感觉。
Step 7: Use the SDK
首先要修改bootargs:
修改bootargs有很多种方法,比如在编译内核的menuconfig时修改其Boot options,或者修改U-Boot里面的config文件,或者在U-Boot运行时指定,等等。由于U-Boot在autoboot的时候会读取boot分区下的uEnv.txt文件,因此将bootargs添加在这个文件中:
bootargs=console=ttyO0, root=/dev/mmcblk0p2 rootwait init=/sbin/init.sysvinit mem=1024M vram=50M
bootcmd= fatload mmc 0 0x uI \
fatload mmc 0 0x maria-am335x. bootm 0x - 0x
uenvcmd=boot
这个uEnv.txt的内容是,设置bootargs,并且设置U-Boot自启动时从SD卡读取dts和uImage。
U-Boot是非常轻量且灵活的,它给人很多意想不到的惊喜。
运行gfxsdkdemos目录下的示例:
~ # cd /opt/gfxsdkdemos/ogles2/
/opt/gfxsdkdemos/ogles2 # ./OGLES2ChameleonMan
/opt/gfxsdkdemos/ogles2 # ./OGLES2MagicLantern
/opt/gfxsdkdemos/ogles2 # cd /opt/gfxsdkdemos/ogles/
/opt/gfxsdkdemos/ogles # ./OGLESEvilSkull
/opt/gfxsdkdemos/ogles # ./OGLESFilmTV
运行OGLES2ChameleonMan这个程序的时候,有没有觉得画面上的这个人跑得很快,图形也没有命令行界面下的拖影呢(好吧,可能只是俺的心理作用~)。
Step 8: Build Qt
(NOTE:触摸屏tslib的调试暂时不考虑。)
到目前为止的目标文件系统,具备了那些内容呢:
有etc目录和其中的启动文件,有存放在bin、sbin目录下的busybox可执行程序,lib库,其他目录如home、media、mnt、proc等,以及存放在opt目录下的Graphics SDK,包括它的库文件、驱动文件和demo文件。只有demo文件无错误的运行在目标板上了,才可以往下进行,否则,要继续修改Kernel代码或者Graphics SDK编译方式。
准备好文件系统,以及解压Qt源代码:
[maria@localhost qt-am335x]$ mkdir roofts.withSDK
[maria@localhost qt-am335x]$ cp ../ro otfs/* rootfs.withSDK/ -rv
[maria@localhost qt-am335x]$ tar xvf ../qt-everywhere-opensource-src-5.4.1.tar.gz -C .
从下面这个地址下载qmake.conf文件,并将它复制进Qt源代码目录,并根据主机的实际情况修改内容:
[maria@localhost qt-am335x]$ tar xvf Linux-TIarmv7-sgx-g++.tar.gz
[maria@localhost qt-am335x]$ ln -s qt-everywhere-opensource-src-5.4.1 qt-everywhere
[maria@localhost qt-am335x]$ cp linux-TIarmv7-sgx-g++ qt-everywhere/qtbase/mkspecs/device/ -r
[maria@localhost qt-am335x]$ vim qt-everywhere/qtbase/mkspecs/device/linux-TIarmv7-sgx-g++/qmake.conf
MAKEFILE_GENERATOR = UNIX
CONFIG += incremental
QMAKE_INCREMENTAL_STYLE = sublib
include(../../common/linux.conf)
include(../../common/gcc-base-unix.conf)
include(../../common/g++-unix.conf)
load(device_config)
QT_QPA_DEFAULT_PLATFORM = eglfs
QT_INSTALL_DIR = /home/maria/qt/qt-am335x/qt-everywhere/qtbase
SGX_SDK_ROOT = /home/maria/qt/graphics/Graphics_SDK_5_01_01_02
COMPILER_FLAGS = -march=armv7-a -mtune=cortex-a8 -mfpu=vfpv3 -mfloat-abi=hard
QMAKE_CFLAGS_RELEASE = -O3 -march=armv7-a -mtune=cortex-a8 -mfpu=vfpv3 -mfloat-abi=hard
QMAKE_CXXFLAGS_RELEASE = -O3 -march=armv7-a -mtune=cortex-a8 -mfpu=vfpv3 -mfloat-abi=hard
QMAKE_CC = arm-linux-gnueabihf-gcc
QMAKE_CXX = arm-linux-gnueabihf-g++
QMAKE_LINK = arm-linux-gnueabihf-g++
QMAKE_LINK_SHLIB = arm-linux-gnueabihf-g++
QMAKE_AR = arm-linux-gnueabihf-ar cqs
QMAKE_OBJCOPY = arm-linux-gnueabihf-objcopy
QMAKE_STRIP = arm-linux-gnueabihf-strip
QMAKE_NM = arm-linux-gnueabihf-nm -P
QMAKE_INCDIR_OPENGL_ES2 = $$SGX_SDK_ROOT/GFX_Linux_SDK/OGLES2/SDKPackage/Builds/OGLES2/Include/
QMAKE_INCDIR_OPENGL_ES2 += $$SGX_SDK_ROOT/include
QMAKE_INCDIR_OPENGL_ES2 += $$SGX_SDK_ROOT/GFX_Linux_SDK/OGLES/SDKPackage/Builds/OGLES/Include/
QMAKE_LIBDIR_OPENGL_ES2 = $$SGX_SDK_ROOT/gfx_dbg_es8.x/
QMAKE_LIBS_OPENGL_ES2 = -lEGL -lGLESv2 -lGLES_CM -lIMGegl -lsrv_um -lusc
QMAKE_INCDIR_OPENGL += $$SGX_SDK_ROOT/GFX_Linux_SDK/OGLES/SDKPackage/Builds/OGLES/Include/
QMAKE_LIBDIR_OPENGL = $$SGX_SDK_ROOT/gfx_dbg_es8.x
QMAKE_LIBDIR_OPENGL_QT = $$SGX_SDK_ROOT/gfx_dbg_es8.x
QMAKE_LIBS_OPENGL_ES1 = -lEGL -lGLES_CM -lIMGegl -lsrv_um -lusc
QMAKE_INCDIR_OPENVG = $$SGX_SDK_ROOT/GFX_Linux_SDK/OVG/SDKPackage/Builds/OVG/Include/
QMAKE_LIBDIR_OPENVG = $$SGX_SDK_ROOT/gfx_dbg_es8.x/
QMAKE_LIBS_OPENVG = -lEGL -lGLESv2 -lGLES_CM -lIMGegl -lsrv_um -lOpenVG -lOpenVGU
QMAKE_INCDIR_EGL = $$QMAKE_INCDIR_OPENGL_ES2
QMAKE_INCDIR_EGL += $$QT_INSTALL_DIR/src/3rdparty/powervr/wsegl2
QMAKE_INCDIR_POWERVR = $$QT_INSTALL_DIR/src/3rdparty/powervr/wsegl2
QMAKE_LIBDIR_EGL = $$QMAKE_LIBDIR_OPENGL_ES2
QMAKE_LIBS_EGL = -lEGL -lIMGegl -lsrv_um -lGLESv2 -lGLES_CM -lusc
QMAKE_INCDIR += $$QMAKE_INCDIR_OPENGL_ES2
QMAKE_LIBDIR += $$QMAKE_LIBDIR_OPENGL_ES2
QMAKE_LIBS = $$QMAKE_LIBS_OPENGL_ES2 -lts -lrt -lpthread
deviceSanityCheckCompiler()
load(qt_config)
NOTE:修改qmake.conf文件,要特别注意它的inluce目录、交叉编译器的设置,以及INCDIR和LIBDIR是否正确;
NOTE:对比Qt的mainline里面的qmake.conf,观察它新增的内容;
NOTE:$$QT_INSTALL_DIR/src/3rdparty/powervr/wsegl2这个目录并不存在,但并不影响编译结果;
另外还要将交叉编译器的bin目录加入环境变量PATH,拷贝头文件和lib(为了省事可以把lib的内容全都拷贝进目标文件系统,但是这里还是暂时采取需要什么就拷贝什么的方法,你甚至先什么都不做,等到编译报错的时候再去寻找对应的lib或者头文件,这样能够更加清晰的理解Qt的编译过程),再执行configure和make步骤:
[maria@localhost qt-everywhere]$ export PATH=$PATH:/opt/i686-arago-linux/usr/bin
[maria@localhost qt-everywhere]$ mkdir /home/maria/qt/qt-am335x/roofts.withSDK/usr/lib
[maria@localhost qt-everywhere]$ cp /opt/ti-sdk-am335x-evm-07.00.00.00/linux-devkit/sysroots/cortexa8hf-vfp-neon-3.8-oe-linux-gnueabi/usr/include /home/maria/qt/qt-am335x/roofts.withSDK/usr/ -r
[maria@localhost qt-everywhere]$ cp /opt/ti-sdk-am335x-evm-07.00.00.00/linux-devkit/sysroots/cortexa8hf-vfp-neon-3.8-oe-linux-gnueabi/usr/lib/crt* /home/maria/qt/qt-am335x/roofts.withSDK/usr/lib/
[maria@localhost qt-everywhere]$ cp /opt/ti-sdk-am335x-evm-07.00.00.00/linux-devkit/sysroots/cortexa8hf-vfp-neon-3.8-oe-linux-gnueabi/usr/lib/libts* /home/maria/qt/qt-am335x/roofts.withSDK/usr/lib/
[maria@localhost qt-everywhere]$ cp /opt/ti-sdk-am335x-evm-07.00.00.00/linux-devkit/sysroots/cortexa8hf-vfp-neon-3.8-oe-linux-gnueabi/usr/lib/librt.* /home/maria/qt/qt-am335x/roofts.withSDK/usr/lib/
[maria@localhost qt-everywhere]$ cp /opt/ti-sdk-am335x-evm-07.00.00.00/linux-devkit/sysroots/cortexa8hf-vfp-neon-3.8-oe-linux-gnueabi/usr/lib/libpthread* /home/maria/qt/qt-am335x/roofts.withSDK/usr/lib/
[maria@localhost qt-everywhere]$ cp /opt/ti-sdk-am335x-evm-07.00.00.00/linux-devkit/sysroots/cortexa8hf-vfp-neon-3.8-oe-linux-gnueabi/usr/lib/libm.* /home/maria/qt/qt-am335x/roofts.withSDK/usr/lib/
[maria@localhost qt-everywhere]$ cp /opt/ti-sdk-am335x-evm-07.00.00.00/linux-devkit/sysroots/cortexa8hf-vfp-neon-3.8-oe-linux-gnueabi/usr/lib/libc.* /home/maria/qt/qt-am335x/roofts.withSDK/usr/lib/
[maria@localhost qt-everywhere]$ cp /opt/ti-sdk-am335x-evm-07.00.00.00/linux-devkit/sysroots/cortexa8hf-vfp-neon-3.8-oe-linux-gnueabi/usr/lib/libc_nonshared.a* /home/maria/qt/qt-am335x/roofts.withSDK/usr/lib/
[maria@localhost qt-everywhere]$ cp /opt/ti-sdk-am335x-evm-07.00.00.00/linux-devkit/sysroots/cortexa8hf-vfp-neon-3.8-oe-linux-gnueabi/usr/lib/libz.so* /home/maria/qt/qt-am335x/roofts.withSDK/usr/lib/
[maria@localhost qt-everywhere]$ cp /opt/ti-sdk-am335x-evm-07.00.00.00/linux-devkit/sysroots/cortexa8hf-vfp-neon-3.8-oe-linux-gnueabi/usr/lib/libjpeg.so* /home/maria/qt/qt-am335x/roofts.withSDK/usr/lib/
[maria@localhost qt-everywhere]$ cp /opt/ti-sdk-am335x-evm-07.00.00.00/linux-devkit/sysroots/cortexa8hf-vfp-neon-3.8-oe-linux-gnueabi/usr/lib/libpng* /home/maria/qt/qt-am335x/roofts.withSDK/usr/lib/
[maria@localhost qt-everywhere]$ cp /opt/ti-sdk-am335x-evm-07.00.00.00/linux-devkit/sysroots/cortexa8hf-vfp-neon-3.8-oe-linux-gnueabi/usr/lib/libnsl.* /home/maria/qt/qt-am335x/roofts.withSDK/usr/lib/
[maria@localhost qt-everywhere]$ cp /opt/ti-sdk-am335x-evm-07.00.00.00/linux-devkit/sysroots/cortexa8hf-vfp-neon-3.8-oe-linux-gnueabi/usr/lib/libgthread-2.0.so* /home/maria/qt/qt-am335x/roofts.withSDK/usr/lib/
[maria@localhost qt-everywhere]$ cp /opt/ti-sdk-am335x-evm-07.00.00.00/linux-devkit/sysroots/cortexa8hf-vfp-neon-3.8-oe-linux-gnueabi/usr/lib/libglib-2.0.so* /home/maria/qt/qt-am335x/roofts.withSDK/usr/lib/
[maria@localhost qt-everywhere]$ cp /opt/ti-sdk-am335x-evm-07.00.00.00/linux-devkit/sysroots/cortexa8hf-vfp-neon-3.8-oe-linux-gnueabi/usr/lib/libasound.so* /home/maria/qt/qt-am335x/roofts.withSDK/usr/lib/
[maria@localhost qt-everywhere]$ cp /opt/ti-sdk-am335x-evm-07.00.00.00/linux-devkit/sysroots/cortexa8hf-vfp-neon-3.8-oe-linux-gnueabi/usr/lib/libdl.* /home/maria/qt/qt-am335x/roofts.withSDK/usr/lib/
[maria@localhost qt-everywhere]$ cp /opt/ti-sdk-am335x-evm-07.00.00.00/linux-devkit/sysroots/cortexa8hf-vfp-neon-3.8-oe-linux-gnueabi/usr/lib/libfreetype.so* /home/maria/qt/qt-am335x/roofts.withSDK/usr/lib/
[maria@localhost qt-everywhere]$ cp /opt/ti-sdk-am335x-evm-07.00.00.00/linux-devkit/sysroots/cortexa8hf-vfp-neon-3.8-oe-linux-gnueabi/usr/lib/glib-2.0 /home/maria/qt/qt-am335x/roofts.withSDK/usr/lib/ -r
[maria@localhost qt-everywhere]$ cp /opt/ti-sdk-am335x-evm-07.00.00.00/linux-devkit/sysroots/cortexa8hf-vfp-neon-3.8-oe-linux-gnueabi/usr/lib/libfontconfig.so* /home/maria/qt/qt-am335x/roofts.withSDK/usr/lib/
[maria@localhost qt-everywhere]$ cp /opt/ti-sdk-am335x-evm-07.00.00.00/linux-devkit/sysroots/cortexa8hf-vfp-neon-3.8-oe-linux-gnueabi/usr/lib/libexpat.so* /home/maria/qt/qt-am335x/roofts.withSDK/usr/lib/
[maria@localhost qt-everywhere]$ cp /opt/ti-sdk-am335x-evm-07.00.00.00/linux-devkit/sysroots/cortexa8hf-vfp-neon-3.8-oe-linux-gnueabi/usr/lib/libdbus* /home/maria/qt/qt-am335x/roofts.withSDK/usr/lib/
[maria@localhost qt-everywhere]$ cp /opt/ti-sdk-am335x-evm-07.00.00.00/linux-devkit/sysroots/cortexa8hf-vfp-neon-3.8-oe-linux-gnueabi/usr/lib/libu* /home/maria/qt/qt-am335x/roofts.withSDK/usr/lib/
[maria@localhost qt-everywhere]$ cp /opt/ti-sdk-am335x-evm-07.00.00.00/linux-devkit/sysroots/cortexa8hf-vfp-neon-3.8-oe-linux-gnueabi/usr/lib/libglslcompiler* /home/maria/qt/qt-am335x/roofts.withSDK/usr/lib/
另外,还要将目标文件系统的include/freetypes2/freetype软链接成include/freetype:
[maria@localhost qt-everywhere]$ cd /home/maria/qt/qt-am335x/roofts.withSDK/usr/include
[maria@localhost include]$ ln -s freetype2/freetype freetype
(如果freetypes报错了就做此修改,没有报错的话就不用管了~)
[maria@localhost qt-everywhere]$ ./configure &help
[maria@localhost qt-everywhere]$ ./configure \
-debug -opensource -confirm-license -shared \
-prefix /home/maria/qt/qt-am335x/qt-everywhere/build \
-sysroot /home/maria/qt/qt-am335x/roofts.withSDK \
-platform linux-g++-64 \
-device linux-TIarmv7-sgx-g++ \
-device-option CROSS_COMPILE=/opt/i686-arago-linux/usr/bin/arm-linux-gnueabihf- \
-D QT_NO_QWS_CURSOR -D QT_QWS_CLIENTBLIT \
-eglfs -opengl es2 -qreal float -v \
-nomake examples -nomake tests
NOTE:configure的编译选项,需要根据主机和目标板的实际情况慢慢摸索,有的编译选项随着新版本的发布不再支持,有的编译选项被添加在新版本中,有的编译错误即使存在也没有关系,有的编译错误则会影响结果。一般来说,提示&Just run 'gmake'&就算是成功。
NOTE:configure会生成很多.o文件,在重新configure之前可以编写脚本,来删除旧有的.o文件。
-prefix: 主机上Qt SDK安装的目录;
-sysroot: 目标文件系统的根目录;
-platform: 主机使用的mkspecs;
-device: 目标机使用的mkspecs,替代xplatform;
-nomake examples -nomake tests: 不编译示例和测试程序,否则得花很长的时间;
[maria@localhost qt-everywhere]$ gmake -j8
[maria@localhost qt-everywhere]$ gmake -j8 install
这里的gmake,是指GNU Make,在Fedora主机上就是make;
编译完成之后,会发现目标文件系统里面增加了build 目录:
[maria@localhost roofts.withSDK]$ find . -mmin 1
./home/maria/qt/qt-am335x/qt-everywhere/build/*
接下来编译示例程序(qmake为上步编译时生成,在/home/maria/qt/qt-am335x/qt-everywhere/build目录下):
[maria@localhost qt-everywhere]$ cd qtbase/examples/
[maria@localhost examples]$ ../../build/bin/qmake examples.pro
[maria@localhost examples]$ gmake -j8
[maria@localhost examples]$ gmake -j8 install
编译完成之后,会发现目标文件系统里面增加了build/examples目录:
[maria@localhost roofts.withSDK]$ find . -mmin 1
./home/maria/qt/qt-am335x/qt-everywhere/build/examples/*
将./home/maria目录拷贝到SD的目标文件系统里;
将./usr/lib和./usr/include也拷贝到SD卡的目标文件系统里;
运行Graphics SDK的335x-demo;
此外,还需要执行下面的步骤(Qt程序会试图获取/etc/machine-id的值,如果运行示例程序时报错,可以主机上的machine-id文件拷贝过来,另外还要设置屏幕的分辨率值):
~ # tftp 192.168.1.118 -g -l machine-id
~# cp machine-id /etc/
~ # export QT_QPA_EGLFS_PHYSICAL_HEIGHT=272
~ # export QT_QPA_EGLFS_PHYSICAL_WIDTH=480
然后执行Qt的示例程序(如果报找不到platform的错误信息,则执行第二条):
~ # /home/maria/qt/qt-am335x/qt-everywhere/build/examples/widgets/widgets/digitalclock/digitalclock
~ # /home/maria/qt/qt-am335x/qt-everywhere/build/examples/widgets/widgets/digitalclock/digitalclock -platform eglfs
到这里,就可以看到液晶上显示的数字时钟啦~
运行Qt程序的时候,可能会发现终端会打印出很多错误,但是不要害怕这些错误,它们提示的信息往往非常关键,比如需要设置哪些环境变量,或者缺乏哪些库文件或者头文件。另外,arm-linux-gnueabihf-ldd和readelf是非常有用的工具,通过它们来观察.so或者可执行程序,往往能够发现很多问题的答案。
Step 9: Build Qt Programs
编写Qt程序,首先要具备C++基础知识;
A. 打开主机上的Qt Creator:
B. 创建一个新项目:
File -& New File or Project -& Application -& Qt Widgets Application
将名字设置为serial_test,目录设置为/home/maria/qt/qt_workspace/serial_test;
然后在manage里面,添加新的Kit:
为Qt Versions添加:/home/maria/qt/qt-am335x/qt-everywhere/build/bin/qmake
为Compilers添加:/opt/i686-arago-linux/usr/bin/arm-linux-gnueabihf-gcc
为Debuggers添加:/opt/i686-arago-linux/usr/bin/arm-linux-gnueabihf-gdb
为Kits添加新的am335x-kit,并将其sysroot、Compiler、Debugger等选成实际的交叉编译类型。
选择Kits为刚刚创建的am335x-kit,然后一路点击next。
C. 将以前的项目mainwindow.ui替代新项目的mainwindow.ui:
D. 将以前的项目mainwindow.h替代新项目的mainwindow.h:
E. 将以前的项目mainwindow.cpp替代新项目的mainwindow.cpp:
(其实我也不想这样的偷懒,但是以前在主机上编写了一个简单的串口应用,正好可以拿来搞这个^_^)
F. 编译项目:
Build -& Build All
G. 将可执行文件拷贝到目标板运行:
生成的可执行文件,存放在serial_test/build-serial_test-am335x-Debug目录下,将它拷贝到目标板上:
~ # tftp 192.168.1.118 -g -l serial_test
~ # chmod +x serial_test
~ # ./serial_test
然后可以看见serial_test的程序界面出现在液晶上,编写基础的Qt应用真的是很简单,因为它的开发环境和跨平台特性都非常的完善^_^。
到这里,SGX+OpenGL+Qt5移植在AM335x+Linux上的基本步骤就算是完成了,虽然还有触摸屏tslib和字体的问题待解决,但还是不放在本文中啦,maybe以后调试的时候再补充进来。
Step 10: About Linux
后记:为什么要选择Linux做硬件开发?
如果Linux真的像很多人所认为的装x专用,毫无用户体验可言,它不会受到那么多人的喜爱。它所能提供的通透、自由和参与的感觉,是做技术的人不可抗拒的诱惑。它的结构极其健壮简洁,并没有很多内容来帮助用户,因此你需要花时间(对我来说是很长的时间)去学习它,但是随着学习的深入,你会发现一个自由的世界打开,你能用极其合理的开销实现非常强大的功能。
对于计算机来说,你不是用户,而是上帝。
使用Linux环境做硬件开发,也是同样的感受,随着开发的进行,你会发现你不仅知道怎么做可以实现硬件的功能,你还能知道为什么要这样做。Linux对它的使用者完全真诚,它只忠实于事物本身的逻辑,而不会为自身的利益为使用者做任何决定,所有的决定都是为了一个最优的最合理的最强壮的未来,它每一个透明的自由的部件,最终提供给了使用者unlimited possibility。
Free不是免费,free是自由,你,值得拥有。
旗下网站:
与非门科技(北京)有限公司 All Rights Reserved.
京ICP证:070212号
北京市公安局备案编号: 京ICP备:号

我要回帖

更多关于 微软surface pro4 的文章

 

随机推荐