【Android 美颜相机】第十一天:GPUImageFilter解析

GPUImageFilter解析

GPUImageFilter 是 Android 平台基于 OpenGL ES 2.0 实现的 GPU 图像滤镜核心基类,为各类图像滤镜(如美颜、风格化特效)提供了统一的初始化、绘制、资源管理、参数配置能力。

本文将逐行解析该类的代码结构、实现逻辑及每行代码的含义。

版权声明与包/类导入

功能说明

该部分包含开源协议声明、包路径定义,以及实现滤镜功能所需的核心类导入,是 Java 类的基础结构。

/* * Copyright (C) 2018 CyberAgent, Inc. // 版权归属:CyberAgent 公司 * * Licensed under the Apache License, Version 2.0 (the "License"); // 遵循 Apache 2.0 开源协议 * you may not use this file except in compliance with the License. // 使用代码需遵守协议约束 * You may obtain a copy of the License at // 协议文本获取地址 * * http://www.apache.org/licenses/LICENSE-2.0 // Apache 2.0 协议官方地址 * * Unless required by applicable law or agreed to in writing, software // 无附加责任声明 * distributed under the License is distributed on an "AS IS" BASIS, // 分发模式:按现状提供 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // 无明示/默示担保 * See the License for the specific language governing permissions and // 协议定义权限与限制 * limitations under the License. */// 声明类所属包路径,归属于 CyberAgent 的 GPUImage 安卓库滤镜模块packagejp.co.cyberagent.android.gpuimage.filter;// 安卓上下文类,用于获取资源(如 Assets)importandroid.content.Context;// 安卓资产管理类,用于读取 assets 目录下的着色器文件importandroid.content.res.AssetManager;// 二维点坐标类,用于传递纹理/顶点坐标点importandroid.graphics.PointF;// OpenGL ES 2.0 核心 API 类,提供 OpenGL 底层调用importandroid.opengl.GLES20;// 输入流类,用于读取 assets 中的着色器文件内容importjava.io.InputStream;// 浮点缓冲区类,用于存储顶点/纹理坐标数据(适配 OpenGL 数据格式)importjava.nio.FloatBuffer;// 链表类,用于存储待执行的绘制任务importjava.util.LinkedList;// OpenGL 工具类(自定义),封装着色器加载、编译等通用操作importjp.co.cyberagent.android.gpuimage.util.OpenGlUtils;

类定义与核心常量

功能说明

定义滤镜基类的核心常量(默认着色器代码),顶点着色器负责处理顶点坐标变换,片元着色器负责处理像素颜色渲染,默认实现“无滤镜”效果(直接输出原纹理)。

// 定义 GPUImageFilter 公共类,所有具体滤镜(如美白、磨皮)均继承此类publicclassGPUImageFilter{// 无滤镜顶点着色器代码:处理顶点坐标和纹理坐标传递publicstaticfinalStringNO_FILTER_VERTEX_SHADER=""+"attribute vec4 position;\n"+// 顶点坐标属性(由 Java 层传入)"attribute vec4 inputTextureCoordinate;\n"+// 纹理坐标属性(由 Java 层传入)" \n"+"varying vec2 textureCoordinate;\n"+// 易变变量:传递纹理坐标到片元着色器" \n"+"void main()\n"+// 顶点着色器主函数"{\n"+" gl_Position = position;\n"+// 设置顶点最终坐标(OpenGL 裁剪空间)" textureCoordinate = inputTextureCoordinate.xy;\n"+// 传递纹理坐标到片元着色器"}";// 无滤镜片元着色器代码:直接采样原纹理像素,无任何颜色修改publicstaticfinalStringNO_FILTER_FRAGMENT_SHADER=""+"varying highp vec2 textureCoordinate;\n"+// 接收顶点着色器传递的纹理坐标(高精度)" \n"+"uniform sampler2D inputImageTexture;\n"+// 输入纹理采样器(由 Java 层绑定)" \n"+"void main()\n"+// 片元着色器主函数"{\n"+" gl_FragColor = texture2D(inputImageTexture, textureCoordinate);\n"+// 采样纹理像素,作为输出颜色"}";

成员变量

功能说明

定义类的核心成员变量,涵盖绘制任务队列、着色器代码、OpenGL 程序/属性/Uniform 句柄、输出尺寸、初始化状态等,是滤镜运行的核心数据载体。

// 待执行的绘制任务链表:存储需要在绘制阶段执行的 OpenGL 操作(如设置 Uniform 参数)privatefinalLinkedList<Runnable>runOnDraw;// 顶点着色器代码(可自定义)privatefinalStringvertexShader;// 片元着色器代码(可自定义)privatefinalStringfragmentShader;// OpenGL 程序 ID:着色器编译链接后的程序句柄privateintglProgId;// position 属性位置:对应顶点着色器中 "position" 变量的句柄privateintglAttribPosition;// 输入纹理 Uniform 位置:对应片元着色器中 "inputImageTexture" 变量的句柄privateintglUniformTexture;// 纹理坐标属性位置:对应顶点着色器中 "inputTextureCoordinate" 变量的句柄privateintglAttribTextureCoordinate;// 滤镜输出宽度privateintoutputWidth;// 滤镜输出高度privateintoutputHeight;// 初始化状态标记:标记 OpenGL 程序是否已初始化完成privatebooleanisInitialized;

构造方法

功能说明

提供无参/有参构造方法,无参构造默认使用“无滤镜”着色器,有参构造支持传入自定义顶点/片元着色器,适配不同滤镜的定制化需求。

// 无参构造方法:默认使用无滤镜顶点/片元着色器publicGPUImageFilter(){this(NO_FILTER_VERTEX_SHADER,NO_FILTER_FRAGMENT_SHADER);}// 有参构造方法:接收自定义顶点/片元着色器代码publicGPUImageFilter(finalStringvertexShader,finalStringfragmentShader){// 初始化绘制任务链表runOnDraw=newLinkedList<>();// 赋值自定义顶点着色器代码this.vertexShader=vertexShader;// 赋值自定义片元着色器代码this.fragmentShader=fragmentShader;}

初始化相关方法

功能说明

封装 OpenGL 程序的初始化逻辑,包括着色器编译链接、属性/Uniform 句柄获取,提供初始化检查、回调扩展等能力,确保滤镜绘制前完成必要的初始化。

// 内部初始化入口方法:封装初始化流程(私有,仅内部调用)privatefinalvoidinit(){// 执行初始化核心逻辑(子类可重写)onInit();// 初始化完成回调(子类可重写扩展)onInitialized();}// 初始化核心逻辑:编译链接着色器程序,获取属性/Uniform 句柄publicvoidonInit(){// 加载并编译顶点/片元着色器,链接为 OpenGL 程序,返回程序 IDglProgId=OpenGlUtils.loadProgram(vertexShader,fragmentShader);// 获取顶点着色器中 "position" 属性的句柄glAttribPosition=GLES20.glGetAttribLocation(glProgId,"position");// 获取片元着色器中 "inputImageTexture" Uniform 的句柄glUniformTexture=GLES20.glGetUniformLocation(glProgId,"inputImageTexture");// 获取顶点着色器中 "inputTextureCoordinate" 属性的句柄glAttribTextureCoordinate=GLES20.glGetAttribLocation(glProgId,"inputTextureCoordinate");// 标记初始化完成isInitialized=true;}// 初始化完成回调方法:空实现,子类可重写(如初始化自定义 Uniform 参数)publicvoidonInitialized(){}// 初始化检查方法:若未初始化则执行 init()publicvoidifNeedInit(){if(!isInitialized)init();}

资源销毁相关方法

功能说明

封装 OpenGL 程序的销毁逻辑,释放显存资源,提供销毁回调扩展,避免内存泄漏。

// 最终销毁方法:标记未初始化,删除 OpenGL 程序,执行销毁回调publicfinalvoiddestroy(){// 标记初始化状态为未完成isInitialized=false;// 删除 OpenGL 程序,释放显存资源GLES20.glDeleteProgram(glProgId);// 执行销毁回调(子类可重写)onDestroy();}// 销毁回调方法:空实现,子类可重写(如释放自定义纹理/缓冲区)publicvoidonDestroy(){}

输出尺寸变化处理

功能说明

响应滤镜输出尺寸变化(如屏幕旋转、视图大小调整),更新宽高参数,适配不同尺寸的渲染需求。

// 输出尺寸变化回调:更新输出宽高(子类可重写扩展)publicvoidonOutputSizeChanged(finalintwidth,finalintheight){// 更新输出宽度outputWidth=width;// 更新输出高度outputHeight=height;}

核心绘制方法

功能说明

滤镜的核心绘制逻辑,负责绑定 OpenGL 程序、传递顶点/纹理坐标数据、绑定纹理、执行绘制操作,是滤镜渲染的核心入口。

// 绘制方法:接收纹理 ID、顶点缓冲区、纹理坐标缓冲区,执行渲染publicvoidonDraw(finalinttextureId,finalFloatBuffercubeBuffer,finalFloatBuffertextureBuffer){// 绑定当前 OpenGL 程序(激活着色器)GLES20.glUseProgram(glProgId);// 执行待处理的绘制任务(如设置 Uniform 参数)runPendingOnDrawTasks();// 若未初始化,直接返回(避免绘制异常)if(!isInitialized){return;}// 重置顶点缓冲区指针到起始位置cubeBuffer.position(0);// 绑定顶点坐标数据到 position 属性:2 个分量/顶点,浮点型,非归一化,步长 0GLES20.glVertexAttribPointer(glAttribPosition,2,GLES20.GL_FLOAT,false,0,cubeBuffer);// 启用 position 属性数组(OpenGL 渲染时读取该属性)GLES20.glEnableVertexAttribArray(glAttribPosition);// 重置纹理坐标缓冲区指针到起始位置textureBuffer.position(0);// 绑定纹理坐标数据到 inputTextureCoordinate 属性:参数含义同顶点坐标GLES20.glVertexAttribPointer(glAttribTextureCoordinate,2,GLES20.GL_FLOAT,false,0,textureBuffer);// 启用 inputTextureCoordinate 属性数组GLES20.glEnableVertexAttribArray(glAttribTextureCoordinate);// 若纹理 ID 有效(非空纹理)if(textureId!=OpenGlUtils.NO_TEXTURE){// 激活纹理单元 0(OpenGL 多纹理单元机制)GLES20.glActiveTexture(GLES20.GL_TEXTURE0);// 绑定纹理 ID 到 GL_TEXTURE_2D 目标GLES20.glBindTexture(GLES20.GL_TEXTURE_2D,textureId);// 设置 inputImageTexture Uniform:绑定到纹理单元 0GLES20.glUniform1i(glUniformTexture,0);}// 绘制前回调(子类可重写,如设置自定义 Uniform 参数)onDrawArraysPre();// 执行绘制:使用 TRIANGLE_STRIP 模式,从第 0 个顶点开始,共 4 个顶点(绘制矩形)GLES20.glDrawArrays(GLES20.GL_TRIANGLE_STRIP,0,4);// 禁用 position 属性数组(绘制完成后释放)GLES20.glDisableVertexAttribArray(glAttribPosition);// 禁用 inputTextureCoordinate 属性数组GLES20.glDisableVertexAttribArray(glAttribTextureCoordinate);// 解绑纹理(避免后续操作干扰)GLES20.glBindTexture(GLES20.GL_TEXTURE_2D,0);}// 绘制前扩展方法:空实现,子类可重写(如设置滤镜强度、颜色等参数)protectedvoidonDrawArraysPre(){}// 执行待处理的绘制任务:遍历链表,执行所有待执行的 Runnable 任务protectedvoidrunPendingOnDrawTasks(){// 同步锁:保证多线程下任务执行安全synchronized(runOnDraw){// 遍历任务链表,直到为空while(!runOnDraw.isEmpty()){// 移除并执行第一个任务runOnDraw.removeFirst().run();}}}

状态与属性获取方法

功能说明

提供初始化状态、输出尺寸、OpenGL 程序/属性句柄的获取方法,方便子类或外部调用。

// 获取初始化状态:返回是否已完成 OpenGL 程序初始化publicbooleanisInitialized(){returnisInitialized;}// 获取输出宽度publicintgetOutputWidth(){returnoutputWidth;}// 获取输出高度publicintgetOutputHeight(){returnoutputHeight;}// 获取 OpenGL 程序 IDpublicintgetProgram(){returnglProgId;}// 获取 position 属性句柄publicintgetAttribPosition(){returnglAttribPosition;}// 获取 inputTextureCoordinate 属性句柄publicintgetAttribTextureCoordinate(){returnglAttribTextureCoordinate;}// 获取 inputImageTexture Uniform 句柄publicintgetUniformTexture(){returnglUniformTexture;}

Uniform 参数设置方法

功能说明

封装不同类型 Uniform 参数的设置逻辑,将参数设置操作加入绘制任务队列,确保在 OpenGL 绘制线程执行(避免线程安全问题)。

// 设置整型 Uniform 参数:接收 Uniform 位置和整型值protectedvoidsetInteger(finalintlocation,finalintintValue){// 将参数设置操作加入绘制任务队列runOnDraw(newRunnable(){@Overridepublicvoidrun(){// 检查并初始化(避免未初始化时操作)ifNeedInit();// 设置 1 个整型 Uniform 参数GLES20.glUniform1i(location,intValue);}});}// 设置浮点型 Uniform 参数:接收 Uniform 位置和浮点值protectedvoidsetFloat(finalintlocation,finalfloatfloatValue){runOnDraw(newRunnable(){@Overridepublicvoidrun(){ifNeedInit();// 设置 1 个浮点型 Uniform 参数GLES20.glUniform1f(location,floatValue);}});}// 设置 2 维浮点向量 Uniform 参数:接收 Uniform 位置和浮点数组protectedvoidsetFloatVec2(finalintlocation,finalfloat[]arrayValue){runOnDraw(newRunnable(){@Overridepublicvoidrun(){ifNeedInit();// 设置 2 维浮点向量 Uniform 参数(1 个向量,从数组起始位置读取)GLES20.glUniform2fv(location,1,FloatBuffer.wrap(arrayValue));}});}// 设置 3 维浮点向量 Uniform 参数protectedvoidsetFloatVec3(finalintlocation,finalfloat[]arrayValue){runOnDraw(newRunnable(){@Overridepublicvoidrun(){ifNeedInit();GLES20.glUniform3fv(location,1,FloatBuffer.wrap(arrayValue));}});}// 设置 4 维浮点向量 Uniform 参数protectedvoidsetFloatVec4(finalintlocation,finalfloat[]arrayValue){runOnDraw(newRunnable(){@Overridepublicvoidrun(){ifNeedInit();GLES20.glUniform4fv(location,1,FloatBuffer.wrap(arrayValue));}});}// 设置浮点数组 Uniform 参数protectedvoidsetFloatArray(finalintlocation,finalfloat[]arrayValue){runOnDraw(newRunnable(){@Overridepublicvoidrun(){ifNeedInit();// 设置浮点数组 Uniform 参数(数组长度为元素个数)GLES20.glUniform1fv(location,arrayValue.length,FloatBuffer.wrap(arrayValue));}});}// 设置 PointF 类型 Uniform 参数(转换为 2 维向量)protectedvoidsetPoint(finalintlocation,finalPointFpoint){runOnDraw(newRunnable(){@Overridepublicvoidrun(){ifNeedInit();// 将 PointF 转换为 2 维浮点数组float[]vec2=newfloat[2];vec2[0]=point.x;vec2[1]=point.y;// 设置 2 维向量 Uniform 参数GLES20.glUniform2fv(location,1,vec2,0);}});}// 设置 3x3 矩阵 Uniform 参数protectedvoidsetUniformMatrix3f(finalintlocation,finalfloat[]matrix){runOnDraw(newRunnable(){@Overridepublicvoidrun(){ifNeedInit();// 设置 3x3 矩阵 Uniform 参数(1 个矩阵,非转置,从数组起始位置读取)GLES20.glUniformMatrix3fv(location,1,false,matrix,0);}});}// 设置 4x4 矩阵 Uniform 参数protectedvoidsetUniformMatrix4f(finalintlocation,finalfloat[]matrix){runOnDraw(newRunnable(){@Overridepublicvoidrun(){ifNeedInit();// 设置 4x4 矩阵 Uniform 参数(参数含义同 3x3 矩阵)GLES20.glUniformMatrix4fv(location,1,false,matrix,0);}});}// 添加绘制任务到队列:子类可调用,添加自定义绘制操作protectedvoidrunOnDraw(finalRunnablerunnable){// 同步锁:保证多线程下任务添加安全synchronized(runOnDraw){// 将任务添加到链表尾部runOnDraw.addLast(runnable);}}

工具方法

功能说明

提供从 assets 目录加载着色器代码的工具方法,以及输入流转字符串的辅助方法,方便加载自定义着色器文件。

// 从 assets 目录加载着色器代码:接收文件路径和上下文publicstaticStringloadShader(Stringfile,Contextcontext){try{// 获取安卓资产管理器AssetManagerassetManager=context.getAssets();// 打开 assets 中的着色器文件InputStreamims=assetManager.open(file);// 将输入流转换为字符串(着色器代码)Stringre=convertStreamToString(ims);// 关闭输入流ims.close();// 返回着色器代码returnre;}catch(Exceptione){// 捕获异常并打印堆栈e.printStackTrace();}// 异常时返回空字符串return"";}// 将输入流转换为字符串:辅助方法,读取 assets 文件内容publicstaticStringconvertStreamToString(java.io.InputStreamis){// 创建 Scanner 对象,以 "\\A" 为分隔符(读取整个流)java.util.Scanners=newjava.util.Scanner(is).useDelimiter("\\A");// 若流中有内容则返回,否则返回空字符串returns.hasNext()?s.next():"";}}

总结

GPUImageFilter 作为安卓 GPU 图像滤镜的基类,核心价值在于:

  1. 封装 OpenGL ES 2.0 底层操作,屏蔽复杂的着色器编译、链接、绘制逻辑,降低子类滤镜的开发成本;
  2. 提供统一的参数配置接口(Uniform 设置),支持整型、浮点型、矩阵等多种类型参数,适配各类滤镜的定制化需求;
  3. 实现资源生命周期管理(初始化/销毁),避免显存泄漏;
  4. 支持从 assets 加载着色器代码,提高滤镜代码的可维护性。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/1190873.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

microblaze是怎么通过把数据通过axi总线给到ip的

User: microblaze是怎么通过把数据通过axi总线给到ip的 Kimi: MicroBlaze 把数据“送”给 IP 并不是靠一根信号线,而是靠“AXI 总线协议”在地址空间上完成一次标准读写。只要 IP 核在 Vivado 里被挂到同一根 AXI 总线…

强烈安利8个AI论文软件,本科生搞定毕业论文!

强烈安利8个AI论文软件&#xff0c;本科生搞定毕业论文&#xff01; AI 工具让论文写作不再难 在当前的学术环境中&#xff0c;越来越多的本科生开始借助 AI 工具来辅助完成毕业论文。这些工具不仅能够帮助学生高效地完成内容创作&#xff0c;还能在降低 AIGC 率、保持语义通顺…

强烈安利8个AI论文软件,本科生搞定毕业论文!

强烈安利8个AI论文软件&#xff0c;本科生搞定毕业论文&#xff01; AI 工具让论文写作不再难 在当前的学术环境中&#xff0c;越来越多的本科生开始借助 AI 工具来辅助完成毕业论文。这些工具不仅能够帮助学生高效地完成内容创作&#xff0c;还能在降低 AIGC 率、保持语义通顺…

solaris vlan网卡设置

首先,查看当前机器的网卡信息: if config -a ls /etc/hostname* 确认当前机器有几块网卡?网卡名? 哪些网卡已经设置了 vlan子网卡。方式一,通过配置文件设置 假如在 e1000g3 网卡上,添加 vlan.107 子网卡,…

第 470 场周赛Q2——3702. 按位异或非零的最长子序列

题目链接&#xff1a;3702. 按位异或非零的最长子序列&#xff08;中等&#xff09; 算法原理&#xff1a; 解法&#xff1a;枚举 2ms击败95.80% 时间复杂度O(N) 先把数组中所有数全部异或在一起&#xff0c;如果异或结果不为零&#xff0c;就直接返回数组长度&#xff0c;如果…

文字标注旋转角度设置(防止文字倒立)

对CAD中曲线进行文字标记时&#xff0c;当文字角度必须随曲线角度时&#xff0c;为避免字头朝下&#xff0c;可采用如下方式ang ang % Math.PI;while (ang < 0) { ang Math.PI; }// 确保文字不会倒立&#xff08;阅读方向从左到右&#xff09;while (ang > Math.PI / 2…

换根 DP 简介

​【换根 DP 简介】● 换根 DP 是树形 DP 的一种重要技术,用于解决需要以树中‌不同节点为根‌分别计算答案的问题。其核心思想是在一次动态规划后,通过‌推导出换根时的状态转移公式‌,高效地计算出所有节点作为根…

文字标注旋转角度设置(防止文字倒立)

对CAD中曲线进行文字标记时&#xff0c;当文字角度必须随曲线角度时&#xff0c;为避免字头朝下&#xff0c;可采用如下方式ang ang % Math.PI;while (ang < 0) { ang Math.PI; }// 确保文字不会倒立&#xff08;阅读方向从左到右&#xff09;while (ang > Math.PI / 2…

【毕业设计】基于机器学习的网络购物平台的智能推荐(源码+文档+远程调试,全bao定制等)

java毕业设计-基于springboot的(源码LW部署文档全bao远程调试代码讲解等) 博主介绍&#xff1a;✌️码农一枚 &#xff0c;专注于大学生项目实战开发、讲解和毕业&#x1f6a2;文撰写修改等。全栈领域优质创作者&#xff0c;博客之星、掘金/华为云/阿里云/InfoQ等平台优质作者、…

储能辅助电力系统调峰的容量需求研究 Matlab代码

✅作者简介&#xff1a;热爱数据处理、建模、算法设计的Matlab仿真开发者。&#x1f34e;更多Matlab代码及仿真咨询内容点击 &#x1f517;&#xff1a;Matlab科研工作室&#x1f34a;个人信条&#xff1a;格物致知,完整Matlab代码获取及仿真咨询内容私信。&#x1f447; 关注我…

咋的,寒假 1 个月学门黑客技术,难道很难吗?

前言 先介绍一下我自己吧&#xff0c;我是一名从事网络安全行业近十年的白帽黑客&#xff0c;在奇安信做了6年的安全研发员&#xff0c;期间大大小小的Hvv也参加了数次&#xff0c;都取得了不错的成绩。本文我就以亲身经验为锚&#xff0c;给那些有着一个黑客梦的小伙伴撰写一份…

【Matlab】 CRC-8 计算数组Checknum

function crc crc8(data) % data: uint8 数组 poly uint8(hex2dec(07)); % 多项式 crc uint8(0); % 初始值for byte datacrc bitxor(crc, byte); % 与输入异或for i 1:8if bitand(crc, 128) % 检查最高位crc bitxor(bitshift(crc, 1), poly);elsecrc bitshift(crc, 1);…

拒绝“数据搬运工”:PostgreSQL 存储过程与函数实战指南

后端兄弟别当搬运工!10行代码省下50%网络开销 快停手,你的 Java/Python 代码正在“谋杀”数据库! 实测数据显示,同样的批量处理逻辑,放在应用层跑比原生数据库慢了整整 10 倍。 连 Stack Overflow 上的高赞回答都直言:“把逻辑离数据近一点,是高性能架构的第一铁律。” …

2026年评价高的镀锌桥架,模压桥架,北方电缆桥架厂家行业优质推荐 - 品牌鉴赏师

引言在现代基础设施建设中,电缆桥架作为电缆敷设的重要支撑和保护装置,其质量和性能直接关系到电力系统的安全稳定运行。为了帮助广大用户在众多电缆桥架厂家中挑选出最优质、最适合的合作伙伴,我们依据一系列科学、…

吐血推荐!本科生AI论文平台TOP10:开题报告文献综述全搞定

吐血推荐&#xff01;本科生AI论文平台TOP10&#xff1a;开题报告文献综述全搞定 2026年本科生AI论文平台测评&#xff1a;为什么你需要这份榜单&#xff1f; 随着人工智能技术的不断进步&#xff0c;越来越多的本科生开始借助AI工具辅助论文写作。然而&#xff0c;面对市场上五…

开源版 Claude Code 杀疯了,怒斩 70k+ Star!!

大家好,我是R哥。 前段时间分享了《2026 AI编程终极套装:Claude Code + Codex + Gemini CLI + Antigravity,四位一体实战指南!!》,还没来得及学习? 别急,2026 年 AI 编程工具又要变天了。。 最近一款号称开源版…

Jetbrains全家桶自动破解

1.下载需要的pycharm与idea等 打开网站查看破解命令 https://liyangxu1.github.io/keyrun/ 2.打开powershell 3.输入: 对应的命令 一路回车即可 Linux: Mac:

UVM-build_phase/run_phase的执行顺序及仿真调度

build_phase build_phase的执行顺序在整个层次上看遵循从上到下,但在一个组件内中的build_phase是顺序顺序执行。create的本质就是创建对象,本质是调用new函数。所以在build_phase中呈现的顺序会出现跳转现象。当在build_phase中执行到create函数时,它会去执行所要创建的组件…

AL_ControlRes代码中文注释

///////////////////////////////////////////////////////////////////////////////////////// /*** \brief 应用程序控制响应函数 (Application Control Response)。* \details 此函数由协议栈周期性地调用&#xff0c;用于处理由应用程序触发的、需要异步完成的状态转换…

Makefile中 =、:=和 ?=的使用方法

理解Makefile中 、:和 ?这三个赋值操作符的区别&#xff0c;对编写可靠高效的构建脚本至关重要。下面这个表格能帮你快速把握它们的核心差异。特性(递归扩展赋值):(简单扩展赋值)?(条件赋值)赋值时机​变量被使用&#xff08;引用&#xff09;时才展开求值变量定义时就立即展…