使用python调用opengl进行渲染 import glfw from OpenGL.GL import * def main(): # Initialize the library if not glfw.init(): return # Create a windowed mode window and its OpenGL context window = glfw.create_window(640, 480, "Hello World", None, None) if not window: glfw.terminate() return # Make the window's context current glfw.make_context_current(window) count =0; # Loop until the user closes the window while not glfw.window_should_close(window): # Render here, e.g. using pyOpenGL glClearColor(0.2, 0.3, 0.3, 1.0) glClear(GL_COLOR_BUFFER_BIT) glColor3f(1.0, 1.0, 1.0) glBegin(GL_TRIANGLES) glVertex3f(-0.5, -0.5, 0.0) glVertex3f(0.5, -0.5, 0.0) glVertex3f(0.0, 0.5, 0.0) glEnd() # Swap front and back buffers glfw.swap_buffers(window) # Poll for and process events glfw.poll_events() glfw.terminate() if __name__ == "__main__": main()
CarPowerManager
实际工作中为了fix某个issue,车载应用需要在车机andoid系统退出STR模式(Suspend to RAM)时候执行某个逻辑 解决方案参照anrdoid文档 注册一个CarPowerStateListener回调,重写onStateChanged 方法 在androidManifest.xml中增加以下权限 <uses-permission android:name="android.car.permission.CAR_POWER" /> 在业务逻辑中注册CarPowerStateListener import android.car.hardware.power.CarPowerManager; import android.car.hardware.power.CarPowerManager.CarPowerStateListener; public class MyService extends Service { private CarPowerManager mCarPowerManager = null; @override public void onCreate() { super.onCreate(); Car car = Car.CreateCar(this); mCarPowerManager = (CarPowerManager)car.getCarManager(Car.POWER_SERVICE); if(mCarPowerManager!=null) { final CarPowerManager.CarPowerStateListener powerListener = new CarPowerManager.CarPowerStateListener () { @Override public void onStateChanged(int state) { Log.i(TAG, "onStateChanged() state = " + state); if(state==SUSPEND_EXIT) //此时退出STR mode { //do my business } } }; } } @override public void onDestroy() { super.onDestroy(); if(mCarPowerManager!=null) { mCarPowerManager.clearListener(); } } }
GlSurfaceView源码剖析
应用程序的渲染方式分为两种 按需渲染: 绝大多数应用程序,比如微信/钉钉/QQ,都是这种,当有数据更新才请求重新刷新绘制界面 定频渲染:比如游戏,永远按照固定的频率进行渲染(只有这样,才能模拟出逼真的动画效果) 在android 中,上述两个场景分别用以下两个类 SurfaceView(按需渲染):直接在UI线程进行渲染,效率低,适用于渲染频率低的应用场景。 GLSurfaceView(定频渲染):开启一个独立的opengl线程来进行渲染(防止UI线程被阻塞),每个GLSurfaceView的实例都有一个 GLThread mGLThread 成员 无论是java/C++, opengl绘制流程都一样: 初始化 egl 参数 在一个循环中不断进行帧绘制 类的大体定义如下 public class GLSurfaceView extends SurfaceView implements SurfaceHolder.Callback2 { private GLThread mGLThread; //独立的opengl线程进行渲染 private Renderer mRenderer; //自定义的Renderer, 这个Render定义了如何进行渲染 ........ public void setRenderer(Renderer renderer) { ......... mRenderer = renderer; mGLThread = new GLThread(mThisWeakRef); mGLThread.start(); //启动opengl线程 } public void queueEvent(Runnable r) { mGLThread.queueEvent(r); } ......... } public class SurfaceView extends View implements ViewRootImpl.SurfaceChangedCallback { SurfaceControl mSurfaceControl; // 与android系统的的surfacefinger服务进行binder通讯 public void draw(Canvas canvas){ ..... super.draw(canvas); } } static class GLThread extends Thread { @Override public void run() { setName("GLThread " + getId()); if (LOG_THREADS) { Log.i("GLThread", "starting tid=" + getId()); } try { guardedRun(); } catch (InterruptedException e) { // fall thru and exit normally } finally { sGLThreadManager.threadExiting(this); } } private void guardedRun() throws InterruptedException { ............. Runnable event = null; while(true){ synchronized (sGLThreadManager) { while (true) { if (mShouldExit) { return; } //pop 一个 event if (! mEventQueue.isEmpty()) { event = mEventQueue.remove(0); break; } if (event != null) { event.run(); // 执行event event = null; continue; } ........... // 初始化egl mEglHelper.createGL(); ........... //onSurfaceCreated mRenderer.onSurfaceCreated(gl, mEglHelper.mEglConfig); if(sizeChanged) //如果view大小发生了变化 { //onSurfaceChanged mRenderer.onSurfaceChanged(gl, w, h); } //绘制 mRenderer.onDrawFrame(gl); ........... } } } } } 自定义Render类 ...
记录一些命令的使用语法
首先linux 下任何命令都可以 $command -h 来显示命令的option Conda conda env list //当前有哪些环境 conda deactivate //退出当前环境 conda list //当前环境安装了哪些package conda remove -n xxx --all //删除xxx环境 conda create -n xxxx //新建一个环境 conda activate xxx //激活某个环境 systemctl 用systemctl对服务进行管理(以nginx为例) systemctl restart nginx //重启nginx systemctl status nginx //查看nginx状态 systemctl show nginx //查看nginx配置文件 nginx nginx -T //测试nginx配置文件 To be continue…
使用frp 和 nginx 进行反向穿透
我有一台空闲的2017年的ThinkPad E470C笔记本,在安装win10系统反复出现蓝屏后,换成ubuntu系统当服务器。在公司环境中,我希望可以远程登录到家里的E470C上做一些实验。我需要买一个有独立IP的外网虚拟主机,虚拟主机上部署frp server 服务,在E470C上部署frp client服务. see: https://gofrp.org/zh-cn/docs/ 步骤 godaddy上买个域名(fangqing.org) 买个虚拟主机,买香港的,不用备案,速度还不错(2G memory,2CPU),有独立IP(x.x.x.x) cloudflare 里注册账号,将域名的解析迁移过去,新增以下域名解析record: CNAME www fangqing.org A fangqing.org x.x.x.x //具体的IP A *.fangqing.org x.x.x.x //泛域名解析 虚拟主机 安装ubuntu系统, ubuntu中安装nginx,fprs(做内网穿透用),用systemctl将nginx和frps增加到开机自启服务中 fprs配置:启动8080端口做http转发 vhostHTTPPort=8080 bindPort = 7000 subdomainHost = "fangqing.org" webServer.addr = "0.0.0.0" webServer.port = 7500 webServer.user = "xxxx" webServer.password = "xxxxx" nginx里新增配置 将对blog.fangqing.org域名的访问forward到frps的8080端口上 ,frps的8080端口会forward到家中内网机器上 server { listen 80; server_name blog.fangqing.org; location / { proxy_redirect off; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_pass http://localhost:8080; } } 家中内网主机 部署nginx(默认80端口) frpc服务配置里增加ssh 和http 服务 serverAddr = "x.x.x.x" serverPort = 7000 [[proxies]] name = "ssh" type = "tcp" localIP = "127.0.0.1" localPort = 22 remotePort = 6000 #通过域名 blog.fangqing.org 访问 [[proxies]] name = "web" type = "http" localPort = 80 subdomain = "blog" #这种方式是直接通过 IP+端口的方式访问(X.X.X.X:8888) [[proxies]] name = "nginx" type = "tcp" localIP = "127.0.0.1" localPort = 80 remotePort = 8888 这样,可以通过x.x.x.x:6000端口ssh到家中的内网主机上,内网主机也给外网主机提供http服务 如此,所有的工作都可以在内网主机上完成 ...