Beispiel #1
0
bool CRendererVTB::UploadTexture(int index)
{
  YUVBUFFER &buf = m_buffers[index];
  YUVPLANE (&planes)[YuvImage::MAX_PLANES] = m_buffers[index].fields[0];

  VTB::CVideoBufferVTB *vb = dynamic_cast<VTB::CVideoBufferVTB*>(buf.videoBuffer);
  if (!vb)
  {
    return false;
  }

  CVImageBufferRef cvBufferRef = vb->GetPB();

  glEnable(m_textureTarget);

  // It is the fastest way to render a CVPixelBuffer backed
  // with an IOSurface as there is no CPU -> GPU upload.
  CGLContextObj cgl_ctx  = (CGLContextObj)g_Windowing.GetCGLContextObj();
  IOSurfaceRef surface  = CVPixelBufferGetIOSurface(cvBufferRef);
  OSType format_type = IOSurfaceGetPixelFormat(surface);

  if (format_type != kCVPixelFormatType_420YpCbCr8BiPlanarVideoRange)
  {
    return false;
  }

  GLsizei surfplanes = IOSurfaceGetPlaneCount(surface);

  if (surfplanes != 2)
  {
    return false;
  }

  GLsizei widthY = IOSurfaceGetWidthOfPlane(surface, 0);
  GLsizei widthUV = IOSurfaceGetWidthOfPlane(surface, 1);
  GLsizei heightY = IOSurfaceGetHeightOfPlane(surface, 0);
  GLsizei heightUV = IOSurfaceGetHeightOfPlane(surface, 1);

  glBindTexture(m_textureTarget, planes[0].id);

  CGLTexImageIOSurface2D(cgl_ctx, m_textureTarget, GL_LUMINANCE,
                         widthY, heightY, GL_LUMINANCE, GL_UNSIGNED_BYTE, surface, 0);
  glTexParameteri(m_textureTarget, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
  glTexParameteri(m_textureTarget, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
  glTexParameteri(m_textureTarget, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
  glTexParameteri(m_textureTarget, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);

  glBindTexture(m_textureTarget, planes[1].id);

  CGLTexImageIOSurface2D(cgl_ctx, m_textureTarget, GL_LUMINANCE_ALPHA,
                         widthUV, heightUV, GL_LUMINANCE_ALPHA, GL_UNSIGNED_BYTE, surface, 1);
  glTexParameteri(m_textureTarget, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
  glTexParameteri(m_textureTarget, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
  glTexParameteri(m_textureTarget, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
  glTexParameteri(m_textureTarget, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);

  glBindTexture(m_textureTarget, 0);

  glDisable(m_textureTarget);

  CalculateTextureSourceRects(index, 3);

  return true;
}
Beispiel #2
0
EGLSurface Display::createPBufferSurface(EGLConfig config, const EGLint *attribList, EGLClientBuffer clientBuffer)
{
	EGLint width = -1, height = -1, ioSurfacePlane = -1;
	EGLenum textureFormat = EGL_NO_TEXTURE;
	EGLenum textureTarget = EGL_NO_TEXTURE;
	EGLenum clientBufferFormat = EGL_NO_TEXTURE;
	EGLenum clientBufferType = EGL_NO_TEXTURE;
	EGLBoolean largestPBuffer = EGL_FALSE;
	const Config *configuration = mConfigSet.get(config);

	if(attribList)
	{
		while(*attribList != EGL_NONE)
		{
			switch(attribList[0])
			{
			case EGL_WIDTH:
				width = attribList[1];
				break;
			case EGL_HEIGHT:
				height = attribList[1];
				break;
			case EGL_LARGEST_PBUFFER:
				largestPBuffer = attribList[1];
				break;
			case EGL_TEXTURE_FORMAT:
				switch(attribList[1])
				{
				case EGL_NO_TEXTURE:
				case EGL_TEXTURE_RGB:
				case EGL_TEXTURE_RGBA:
					textureFormat = attribList[1];
					break;
				default:
					return error(EGL_BAD_ATTRIBUTE, EGL_NO_SURFACE);
				}
				break;
			case EGL_TEXTURE_INTERNAL_FORMAT_ANGLE:
				switch(attribList[1])
				{
				case GL_RED:
				case GL_R16UI:
				case GL_RG:
				case GL_BGRA_EXT:
				case GL_RGBA:
					clientBufferFormat = attribList[1];
					break;
				default:
					return error(EGL_BAD_ATTRIBUTE, EGL_NO_SURFACE);
				}
				break;
			case EGL_TEXTURE_TYPE_ANGLE:
				switch(attribList[1])
				{
				case GL_UNSIGNED_BYTE:
				case GL_UNSIGNED_SHORT:
				case GL_HALF_FLOAT_OES:
				case GL_HALF_FLOAT:
					clientBufferType = attribList[1];
					break;
				default:
					return error(EGL_BAD_ATTRIBUTE, EGL_NO_SURFACE);
				}
				break;
			case EGL_IOSURFACE_PLANE_ANGLE:
				if(attribList[1] < 0)
				{
					return error(EGL_BAD_ATTRIBUTE, EGL_NO_SURFACE);
				}
				ioSurfacePlane = attribList[1];
				break;
			case EGL_TEXTURE_TARGET:
				switch(attribList[1])
				{
				case EGL_NO_TEXTURE:
				case EGL_TEXTURE_2D:
				case EGL_TEXTURE_RECTANGLE_ANGLE:
					textureTarget = attribList[1];
					break;
				default:
					return error(EGL_BAD_ATTRIBUTE, EGL_NO_SURFACE);
				}
				break;
			case EGL_MIPMAP_TEXTURE:
				if(attribList[1] != EGL_FALSE)
				{
					UNIMPLEMENTED();
					return error(EGL_BAD_MATCH, EGL_NO_SURFACE);
				}
				break;
			case EGL_VG_COLORSPACE:
				return error(EGL_BAD_MATCH, EGL_NO_SURFACE);
			case EGL_VG_ALPHA_FORMAT:
				return error(EGL_BAD_MATCH, EGL_NO_SURFACE);
			default:
				return error(EGL_BAD_ATTRIBUTE, EGL_NO_SURFACE);
			}

			attribList += 2;
		}
	}

	if(width < 0 || height < 0)
	{
		return error(EGL_BAD_PARAMETER, EGL_NO_SURFACE);
	}

	if(width == 0 || height == 0)
	{
		return error(EGL_BAD_ATTRIBUTE, EGL_NO_SURFACE);
	}

	if((textureFormat != EGL_NO_TEXTURE && textureTarget == EGL_NO_TEXTURE) ||
	   (textureFormat == EGL_NO_TEXTURE && textureTarget != EGL_NO_TEXTURE))
	{
		return error(EGL_BAD_MATCH, EGL_NO_SURFACE);
	}

	if(!(configuration->mSurfaceType & EGL_PBUFFER_BIT))
	{
		return error(EGL_BAD_MATCH, EGL_NO_SURFACE);
	}

	if(clientBuffer)
	{
		switch(clientBufferType)
		{
		case GL_UNSIGNED_BYTE:
			switch(clientBufferFormat)
			{
			case GL_RED:
			case GL_RG:
			case GL_BGRA_EXT:
				break;
			case GL_R16UI:
			case GL_RGBA:
				return error(EGL_BAD_ATTRIBUTE, EGL_NO_SURFACE);
			default:
				return error(EGL_BAD_PARAMETER, EGL_NO_SURFACE);
			}
			break;
		case GL_UNSIGNED_SHORT:
			switch(clientBufferFormat)
			{
			case GL_R16UI:
				break;
			case GL_RED:
			case GL_RG:
			case GL_BGRA_EXT:
			case GL_RGBA:
				return error(EGL_BAD_ATTRIBUTE, EGL_NO_SURFACE);
			default:
				return error(EGL_BAD_PARAMETER, EGL_NO_SURFACE);
			}
			break;
		case GL_HALF_FLOAT_OES:
		case GL_HALF_FLOAT:
			switch(clientBufferFormat)
			{
			case GL_RGBA:
				break;
			case GL_RED:
			case GL_R16UI:
			case GL_RG:
			case GL_BGRA_EXT:
				return error(EGL_BAD_ATTRIBUTE, EGL_NO_SURFACE);
			default:
				return error(EGL_BAD_PARAMETER, EGL_NO_SURFACE);
			}
			break;
		default:
			return error(EGL_BAD_PARAMETER, EGL_NO_SURFACE);
		}

		if(ioSurfacePlane < 0)
		{
			return error(EGL_BAD_PARAMETER, EGL_NO_SURFACE);
		}

		if(textureFormat != EGL_TEXTURE_RGBA)
		{
			return error(EGL_BAD_ATTRIBUTE, EGL_NO_SURFACE);
		}

		if(textureTarget != EGL_TEXTURE_RECTANGLE_ANGLE)
		{
			return error(EGL_BAD_ATTRIBUTE, EGL_NO_SURFACE);
		}

#if defined(__APPLE__)
		IOSurfaceRef ioSurface = reinterpret_cast<IOSurfaceRef>(clientBuffer);
		size_t planeCount = IOSurfaceGetPlaneCount(ioSurface);
		if((static_cast<size_t>(width) > IOSurfaceGetWidthOfPlane(ioSurface, ioSurfacePlane)) ||
		   (static_cast<size_t>(height) > IOSurfaceGetHeightOfPlane(ioSurface, ioSurfacePlane)) ||
		   ((planeCount != 0) && static_cast<size_t>(ioSurfacePlane) >= planeCount))
		{
			return error(EGL_BAD_ATTRIBUTE, EGL_NO_SURFACE);
		}
#endif
	}
	else
	{
		if((textureFormat == EGL_TEXTURE_RGB && configuration->mBindToTextureRGB != EGL_TRUE) ||
		   ((textureFormat == EGL_TEXTURE_RGBA && configuration->mBindToTextureRGBA != EGL_TRUE)))
		{
			return error(EGL_BAD_ATTRIBUTE, EGL_NO_SURFACE);
		}
	}

	Surface *surface = new PBufferSurface(this, configuration, width, height, textureFormat, textureTarget, clientBufferFormat, clientBufferType, largestPBuffer, clientBuffer, ioSurfacePlane);

	if(!surface->initialize())
	{
		surface->release();
		return EGL_NO_SURFACE;
	}

	surface->addRef();
	mSurfaceSet.insert(surface);

	return success(surface);
}