Beispiel #1
0
void WinEGLView::CreateContext()
{
	EGLint contextAttributes[32];
	uint i = 0;
	switch (mGLESVersion)
	{
	case 2:
		contextAttributes[i++] = EGL_CONTEXT_CLIENT_VERSION;
		contextAttributes[i++] = 2;
		break;
	case 3:
		contextAttributes[i++] = EGL_CONTEXT_CLIENT_VERSION;
		contextAttributes[i++] = 3;
		break;
	case 1:
	default:
		contextAttributes[i++] = EGL_CONTEXT_CLIENT_VERSION;
		contextAttributes[i++] = 1;
		break;
	}

	contextAttributes[i] = EGL_NONE;


	mEGLContext = eglCreateContext(mEGLDisplay, mEGLConfig, nullptr, contextAttributes);
	MEDUSA_ASSERT_NOT_EQUAL(mEGLContext, EGL_NO_CONTEXT, "");
	MEDUSA_ASSERT_FALSE(GetEGLError(), "");
}
Beispiel #2
0
static int CreateTextureFromHandle(EGLDisplay egl_display,
                                   buffer_handle_t handle,
                                   AutoEGLImageAndGLTexture *out) {
  EGLImageKHR image = eglCreateImageKHR(
      egl_display, EGL_NO_CONTEXT, EGL_NATIVE_HANDLE_ANDROID_NVX,
      (EGLClientBuffer)handle, NULL /* no attribs */);

  if (image == EGL_NO_IMAGE_KHR) {
    ALOGE("Failed to make image %s %p", GetEGLError(), handle);
    return -EINVAL;
  }

  GLuint texture;
  glGenTextures(1, &texture);
  glBindTexture(GL_TEXTURE_2D, texture);
  glEGLImageTargetTexture2DOES(GL_TEXTURE_2D, (GLeglImageOES)image);
  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
  glBindTexture(GL_TEXTURE_2D, 0);

  out->image.reset(image);
  out->texture.reset(texture);

  return 0;
}
Beispiel #3
0
static int EGLFenceWait(EGLDisplay egl_display, int acquireFenceFd) {
  int ret = 0;

  EGLint attribs[] = {EGL_SYNC_NATIVE_FENCE_FD_ANDROID, acquireFenceFd,
                      EGL_NONE};
  EGLSyncKHR egl_sync =
      eglCreateSyncKHR(egl_display, EGL_SYNC_NATIVE_FENCE_ANDROID, attribs);
  if (egl_sync == EGL_NO_SYNC_KHR) {
    ALOGE("Failed to make EGLSyncKHR from acquireFenceFd: %s", GetEGLError());
    close(acquireFenceFd);
    return 1;
  }

  EGLint success = eglWaitSyncKHR(egl_display, egl_sync, 0);
  if (success == EGL_FALSE) {
    ALOGE("Failed to wait for acquire: %s", GetEGLError());
    ret = 1;
  }
  eglDestroySyncKHR(egl_display, egl_sync);

  return ret;
}
Beispiel #4
0
void WinEGLView::CreateSurface()
{
	EGLint	surfaceAttributes[16];
	uint i = 0;

	surfaceAttributes[i++] = EGL_NONE;

	if (mIsNeedPixmap)
	{
		mEGLSurface = eglCreatePixmapSurface(mEGLDisplay, mEGLConfig, mBitmapPixmap, surfaceAttributes);
	}
	else
	{
		mEGLSurface = eglCreateWindowSurface(mEGLDisplay, mEGLConfig, mEGLNativeWindow, surfaceAttributes);
		if (mEGLSurface == EGL_NO_SURFACE)
		{
			eglGetError(); // Clear error
			mEGLSurface = eglCreateWindowSurface(mEGLDisplay, mEGLConfig, nullptr, surfaceAttributes);
		}
	}

	MEDUSA_ASSERT_NOT_EQUAL(mEGLSurface, EGL_NO_SURFACE, "");
	MEDUSA_ASSERT_FALSE(GetEGLError(), "");
}
Beispiel #5
0
bool WinEGLView::Initialize()
{
	RETURN_FALSE_IF_FALSE(BaseRenderView::Initialize());


	MEDUSA_ASSERT_TRUE(mParent->IsA<IWindow>(), "");
	WinWindow* window = (WinWindow*)(INode*)mParent;

	EGLNativeWindowType eglNativeWindow = window->WindowHandle();

	mEGLNativeWindow = eglNativeWindow;
	mEGLNativeDisplay = EGL_DEFAULT_DISPLAY;
	mEGLDisplay = EGL_NO_DISPLAY;
	mEGLConfig = 0;
	mEGLSurface = EGL_NO_SURFACE;
	mEGLContext = EGL_NO_CONTEXT;

	mPixmapDisplay = 0;
	mBitmapPixmap = 0;
	mBitmapPixmapOld = 0;

	/*
	Step 0 - Create a NativeWindowType that we can use for OpenGL ES output
	*/


	/*
	Step 1 - Get the default display.
	EGL uses the concept of a "display" which in most environments
	corresponds to a single physical screen. Since we usually want
	to draw to the main screen or only have a single screen to begin
	with, we let EGL pick the default display.
	Querying other displays is platform specific.
	*/
	mEGLNativeDisplay = GetDC(mEGLNativeWindow);

	mEGLDisplay = eglGetDisplay(mEGLNativeDisplay);
	if (mEGLDisplay == EGL_NO_DISPLAY)
	{
		mEGLDisplay = eglGetDisplay(EGL_DEFAULT_DISPLAY);
	}
	MEDUSA_ASSERT_NOT_EQUAL(mEGLDisplay, EGL_NO_DISPLAY, "");

	if (mIsNeedPixmap)
	{
		mPixmapDisplay = CreateCompatibleDC(mEGLNativeDisplay);
		Size2F screenSize = ResolutionAdapter::Instance().WinSize();
		mBitmapPixmap = CreateCompatibleBitmap(mEGLNativeDisplay, (uint)screenSize.Width, (uint)screenSize.Height);
	}

	/*
	Step 2 - Initialize EGL.
	EGL has to be initialized with the display obtained in the
	previous step. We cannot use other EGL functions except
	eglGetDisplay and eglGetError before eglInitialize has been
	called.
	If we're not interested in the EGL version number we can just
	pass nullptr for the second and third parameters.
	*/

	EGLint majorVersion, minorVersion;
	EGLBoolean result = eglInitialize(mEGLDisplay, &majorVersion, &minorVersion);
	MEDUSA_ASSERT_NOT_ZERO(result, "");

	//ASSERT_NOT_EQUAL(majorVersion,1);

	/*
	Step 3 - Specify the required configuration attributes.
	An EGL "configuration" describes the pixel format and type of
	surfaces that can be used for drawing.
	For now we just want to use a 16 bit RGB surface that is a
	Window surface, i.e. it will be visible on screen. The list
	has to contain key/value pairs, terminated with EGL_NONE.
	*/
	eglBindAPI(EGL_OPENGL_ES_API);
	MEDUSA_ASSERT_FALSE(GetEGLError(), "");

	/*
	Step 4 - Find a config that matches all requirements.
	eglChooseConfig provides a list of all available configurations
	that meet or exceed the requirements given as the second
	argument. In most cases we just want the first config that meets
	all criteria, so we can limit the number of configs returned to 1.
	*/

	mEGLConfig = ChooseConfig();

	/*
	Step 5 - Create a surface to draw to.
	Use the config picked in the previous step and the native window
	handle when available to create a window surface. A window surface
	is one that will be visible on screen inside the native display (or
	full screen if there is no windowing system).
	Pixmaps and pbuffers are surfaces which only exist in off-screen
	memory.
	*/
	CreateSurface();


	/*
	Step 6 - Create a context.
	EGL has to create a context for OpenGL ES. Our OpenGL ES resources
	like textures will only be valid inside this context
	(or shared contexts)
	*/
	CreateContext();


	/*
	Step 7 - Bind the context to the current thread and use our
	window surface for drawing and reading.
	Contexts are bound to a thread. This means you don't have to
	worry about other threads and processes interfering with your
	OpenGL ES application.
	We need to specify a surface that will be the target of all
	subsequent drawing operations, and one that will be the source
	of read operations. They can be the same surface.
	*/

	//ASSERT_NOT_EQUAL(eglSurface,EGL_NO_SURFACE,0);

	eglMakeCurrent(mEGLDisplay, mEGLSurface, mEGLSurface, mEGLContext);
	MEDUSA_ASSERT_FALSE(GetEGLError(), "");
	/*
	Step 8 - Draw something with OpenGL ES.
	At this point everything is initialized and we're ready to use
	OpenGL ES to draw something on the screen.
	*/
	if (mIsNeedPixmap)
	{
		mBitmapPixmapOld = (EGLNativePixmapType)SelectObject(mPixmapDisplay, mBitmapPixmap);
	}
	//SetForegroundWindow(mEGLNativeWindow);

	RenderEngine::Instance().Initialize();

	return true;

}
Beispiel #6
0
int GLWorker::Compositor::Composite(hwc_layer_1 *layers, size_t num_layers,
                                    sp<GraphicBuffer> framebuffer) {
  ATRACE_CALL();
  int ret = 0;
  size_t i;
  std::vector<AutoEGLImageAndGLTexture> layer_textures;
  std::vector<RenderingCommand> commands;

  if (num_layers == 0) {
    return -EALREADY;
  }

  GLint frame_width = framebuffer->getWidth();
  GLint frame_height = framebuffer->getHeight();
  EGLSyncKHR finished_sync;

  AutoEGLImageKHR egl_fb_image(
      eglCreateImageKHR(egl_display_, EGL_NO_CONTEXT, EGL_NATIVE_BUFFER_ANDROID,
                        (EGLClientBuffer)framebuffer->getNativeBuffer(),
                        NULL /* no attribs */),
      EGLImageDeleter(egl_display_));

  if (egl_fb_image.get() == EGL_NO_IMAGE_KHR) {
    ALOGE("Failed to make image from target buffer: %s", GetEGLError());
    return -EINVAL;
  }

  GLuint gl_fb_tex;
  glGenTextures(1, &gl_fb_tex);
  AutoGLTexture gl_fb_tex_auto(gl_fb_tex);
  glBindTexture(GL_TEXTURE_2D, gl_fb_tex);
  glEGLImageTargetTexture2DOES(GL_TEXTURE_2D,
                               (GLeglImageOES)egl_fb_image.get());
  glBindTexture(GL_TEXTURE_2D, 0);

  GLuint gl_fb;
  glGenFramebuffers(1, &gl_fb);
  AutoGLFramebuffer gl_fb_auto(gl_fb);
  glBindFramebuffer(GL_FRAMEBUFFER, gl_fb);
  glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D,
                         gl_fb_tex, 0);

  if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE) {
    ALOGE("Failed framebuffer check for created target buffer: %s",
          GetGLFramebufferError());
    return -EINVAL;
  }

  for (i = 0; i < num_layers; i++) {
    const struct hwc_layer_1 *layer = &layers[i];

    if (ret) {
      if (layer->acquireFenceFd >= 0)
        close(layer->acquireFenceFd);
      continue;
    }

    layer_textures.emplace_back(egl_display_);
    ret = CreateTextureFromHandle(egl_display_, layer->handle,
                                  &layer_textures.back());
    if (!ret) {
      ret = EGLFenceWait(egl_display_, layer->acquireFenceFd);
    }
    if (ret) {
      layer_textures.pop_back();
      ret = -EINVAL;
    }
  }

  if (ret)
    return ret;

  ConstructCommands(layers, num_layers, &commands);

  glViewport(0, 0, frame_width, frame_height);

  glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
  glClear(GL_COLOR_BUFFER_BIT);

  glBindBuffer(GL_ARRAY_BUFFER, vertex_buffer_.get());
  glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, sizeof(float) * 4, NULL);
  glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, sizeof(float) * 4,
                        (void *)(sizeof(float) * 2));
  glEnableVertexAttribArray(0);
  glEnableVertexAttribArray(1);
  glEnable(GL_SCISSOR_TEST);

  for (const RenderingCommand &cmd : commands) {
    if (cmd.texture_count <= 0) {
      continue;
    }

    // TODO(zachr): handle the case of too many overlapping textures for one
    // area by falling back to rendering as many layers as possible using
    // multiple blending passes.
    if (cmd.texture_count > blend_programs_.size()) {
      ALOGE("Too many layers to render in one area");
      continue;
    }

    GLint program = blend_programs_[cmd.texture_count - 1].get();
    glUseProgram(program);
    GLint gl_viewport_loc = glGetUniformLocation(program, "uViewport");
    GLint gl_tex_loc = glGetUniformLocation(program, "uLayerTextures");
    GLint gl_crop_loc = glGetUniformLocation(program, "uLayerCrop");
    GLint gl_alpha_loc = glGetUniformLocation(program, "uLayerAlpha");
    glUniform4f(gl_viewport_loc, cmd.bounds[0] / (float)frame_width,
                cmd.bounds[1] / (float)frame_height,
                (cmd.bounds[2] - cmd.bounds[0]) / (float)frame_width,
                (cmd.bounds[3] - cmd.bounds[1]) / (float)frame_height);

    for (unsigned src_index = 0; src_index < cmd.texture_count; src_index++) {
      const RenderingCommand::TextureSource &src = cmd.textures[src_index];
      glUniform1f(gl_alpha_loc + src_index, src.alpha);
      glUniform4f(gl_crop_loc + src_index, src.crop_bounds[0],
                  src.crop_bounds[1], src.crop_bounds[2] - src.crop_bounds[0],
                  src.crop_bounds[3] - src.crop_bounds[1]);

      glUniform1i(gl_tex_loc + src_index, src_index);
      glActiveTexture(GL_TEXTURE0 + src_index);
      glBindTexture(GL_TEXTURE_2D,
                    layer_textures[src.texture_index].texture.get());
    }

    glScissor(cmd.bounds[0], cmd.bounds[1], cmd.bounds[2] - cmd.bounds[0],
              cmd.bounds[3] - cmd.bounds[1]);
    glDrawArrays(GL_TRIANGLES, 0, 3);

    for (unsigned src_index = 0; src_index < cmd.texture_count; src_index++) {
      glActiveTexture(GL_TEXTURE0 + src_index);
      glBindTexture(GL_TEXTURE_2D, 0);
    }
  }

  glDisable(GL_SCISSOR_TEST);
  glActiveTexture(GL_TEXTURE0);
  glDisableVertexAttribArray(0);
  glDisableVertexAttribArray(1);
  glBindBuffer(GL_ARRAY_BUFFER, 0);
  glUseProgram(0);

  glBindFramebuffer(GL_FRAMEBUFFER, 0);

  return ret;
}
Beispiel #7
0
GLWorker::Compositor::~Compositor() {
  if (egl_display_ != EGL_NO_DISPLAY && egl_ctx_ != EGL_NO_CONTEXT)
    if (eglDestroyContext(egl_display_, egl_ctx_) == EGL_FALSE)
      ALOGE("Failed to destroy OpenGL ES Context: %s", GetEGLError());
}
Beispiel #8
0
int GLWorker::Compositor::Init() {
  int ret = 0;
  const char *egl_extensions;
  const char *gl_extensions;
  EGLint num_configs;
  EGLint attribs[] = {EGL_WIDTH, 1, EGL_HEIGHT, 1, EGL_NONE, EGL_NONE};
  EGLConfig egl_config;

  // clang-format off
  const GLfloat verts[] = {
    0.0f,  0.0f,    0.0f, 0.0f,
    0.0f,  2.0f,    0.0f, 2.0f,
    2.0f,  0.0f,    2.0f, 0.0f
  };
  // clang-format on

  const EGLint config_attribs[] = {EGL_RENDERABLE_TYPE,
                                   EGL_OPENGL_ES2_BIT,
                                   EGL_RED_SIZE,
                                   8,
                                   EGL_GREEN_SIZE,
                                   8,
                                   EGL_BLUE_SIZE,
                                   8,
                                   EGL_NONE};

  const EGLint context_attribs[] = {EGL_CONTEXT_CLIENT_VERSION, 3, EGL_NONE};

  egl_display_ = eglGetDisplay(EGL_DEFAULT_DISPLAY);
  if (egl_display_ == EGL_NO_DISPLAY) {
    ALOGE("Failed to get egl display");
    return 1;
  }

  if (!eglInitialize(egl_display_, NULL, NULL)) {
    ALOGE("Failed to initialize egl: %s", GetEGLError());
    return 1;
  }

  egl_extensions = eglQueryString(egl_display_, EGL_EXTENSIONS);

  // These extensions are all technically required but not always reported due
  // to meta EGL filtering them out.
  if (!HasExtension("EGL_KHR_image_base", egl_extensions))
    ALOGW("EGL_KHR_image_base extension not supported");

  if (!HasExtension("EGL_ANDROID_image_native_buffer", egl_extensions))
    ALOGW("EGL_ANDROID_image_native_buffer extension not supported");

  if (!HasExtension("EGL_ANDROID_native_fence_sync", egl_extensions))
    ALOGW("EGL_ANDROID_native_fence_sync extension not supported");

  if (!eglChooseConfig(egl_display_, config_attribs, &egl_config, 1,
                       &num_configs)) {
    ALOGE("eglChooseConfig() failed with error: %s", GetEGLError());
    return 1;
  }

  egl_ctx_ =
      eglCreateContext(egl_display_, egl_config,
                       EGL_NO_CONTEXT /* No shared context */, context_attribs);

  if (egl_ctx_ == EGL_NO_CONTEXT) {
    ALOGE("Failed to create OpenGL ES Context: %s", GetEGLError());
    return 1;
  }

  if (!eglMakeCurrent(egl_display_, EGL_NO_SURFACE, EGL_NO_SURFACE, egl_ctx_)) {
    ALOGE("Failed to make the OpenGL ES Context current: %s", GetEGLError());
    return 1;
  }

  gl_extensions = (const char *)glGetString(GL_EXTENSIONS);

  if (!HasExtension("GL_OES_EGL_image", gl_extensions))
    ALOGW("GL_OES_EGL_image extension not supported");

  GLuint vertex_buffer;
  glGenBuffers(1, &vertex_buffer);
  glBindBuffer(GL_ARRAY_BUFFER, vertex_buffer);
  glBufferData(GL_ARRAY_BUFFER, sizeof(verts), verts, GL_STATIC_DRAW);
  glBindBuffer(GL_ARRAY_BUFFER, 0);
  vertex_buffer_.reset(vertex_buffer);

  if (GenerateShaders(&blend_programs_)) {
    return 1;
  }

  return 0;
}