【问题标题】:Android NDK - Load texture from other threadAndroid NDK - 从其他线程加载纹理
【发布时间】:2012-07-26 18:19:45
【问题描述】:

我尝试为我的 Android NDK 游戏项目编写加载屏幕 - 以预加载所有纹理。 如果在其他线程中创建纹理,我会正确设置纹理宽度等值,但即使 glGetError 返回 0,也会得到黑色精灵而不是纹理精灵。在同一个线程中一切正常,因此假设精灵或纹理代码中没有错误.

我认为这是因为我尝试从另一个线程调用 opengl es 2.0 函数,而没有 EGL 提供的上下文。但是如何从 EGL 中获取 opengl es 2.0 上下文,它是在 Java (Android) 中创建的,并将其绑定到本机 C 中的 opengl es 2.0 函数中使用?

Java(Android)

public class OGLES2View extends GLSurfaceView
{
 private static final int OGLES_VERSION = 2;

 public OGLES2View(Context context)
 {
  super(context);
  setEGLContextClientVersion(OGLES_VERSION);
  setRenderer(new OGLES2Renderer());
 }

private GLSurfaceView ogles2SurfaceView = null;

@Override
public void onCreate(Bundle savedInstanceState)
{
    super.onCreate(savedInstanceState);
    ogles2SurfaceView = new OGLES2View(this);
    setContentView(ogles2SurfaceView);
}

C

#define TRUE 1
#define FALSE 0

typedef unsigned char bool;

typedef struct game_data
{
 bool loaded;
 tex* t;
}game_data;

static void* loader_thread_func(void* arg)
{
 JavaVM* jvm = get_java_vm(); //get java VM to detach in the end
 JNIEnv* env = get_jni_env(); //== attach current thread
 game_data* to_load = (game_data*) arg;
 to_load->t = malloc(sizeof(tex));
 set_tex(to_load->t,"textures/bonus.png");//textures width and height set correctly
 to_load->loaded = TRUE;
 (*jvm)->DetachCurrentThread(jvm);
 return NULL;
}

void load_game_data(game_data* res)
{
 pthread_t loader_thread;
 pthread_create(&loader_thread, NULL, loader_thread_func, res);
}

/*in render manager file*/
static game_data* g_d = NULL;

/*in onInit func*/
g_d = malloc(sizeof(game_data));
g_d->loaded = FALSE;
load_game_data(g_d);

/*in onDraw function*/
 if(g_d->loaded)
 /*draw sprite*/

【问题讨论】:

    标签: java c android-ndk opengl-es-2.0


    【解决方案1】:

    要从另一个线程调用 OpenGL ES 函数,您必须在 2 个线程之间创建一个共享的 OpenGL ES 上下文。

    有一个更简单的解决方案 - 将事件发送到拥有 OpenGL ES 上下文的线程,以便在纹理加载到第二个线程后立即更新它。

    【讨论】:

      【解决方案2】:

      Android 不支持共享 OpenGL 上下文,因此您必须使用主上下文来创建纹理。您可以在后台线程上加载纹理数据,但使用该数据创建纹理必须在主上下文中完成。 Sergey 建议在加载纹理数据后将事件发送到主线程是 Android 上的正确做法。

      【讨论】:

      • 自 GLES20 以来,Android 确实支持共享上下文。任何使用 GLSurfaceView 的人都必须使用共享上下文来访问 GLES30 功能(如位 blitting)。使用 GLES30,可以打包真正的缓冲区对象,并用于将纹理异步传输到 GL 线程。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-09-13
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-03-09
      • 1970-01-01
      相关资源
      最近更新 更多