• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2016 The SwiftShader Authors. All Rights Reserved.
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 //    http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14 
15 // Texture.cpp: Implements the Texture class and its derived classes
16 // Texture2D and TextureCubeMap. Implements GL texture objects and related
17 // functionality. [OpenGL ES 2.0.24] section 3.7 page 63.
18 
19 #include "Texture.h"
20 
21 #include "main.h"
22 #include "mathutil.h"
23 #include "Framebuffer.h"
24 #include "Device.hpp"
25 #include "libEGL/Display.h"
26 #include "common/Surface.hpp"
27 #include "common/debug.h"
28 
29 #include <algorithm>
30 
31 namespace es1
32 {
33 
Texture(GLuint name)34 Texture::Texture(GLuint name) : egl::Texture(name)
35 {
36 	mMinFilter = GL_NEAREST_MIPMAP_LINEAR;
37 	mMagFilter = GL_LINEAR;
38 	mWrapS = GL_REPEAT;
39 	mWrapT = GL_REPEAT;
40 	mMaxAnisotropy = 1.0f;
41 	generateMipmap = GL_FALSE;
42 	cropRectU = 0;
43 	cropRectV = 0;
44 	cropRectW = 0;
45 	cropRectH = 0;
46 
47 	resource = new sw::Resource(0);
48 }
49 
~Texture()50 Texture::~Texture()
51 {
52 	resource->destruct();
53 }
54 
getResource() const55 sw::Resource *Texture::getResource() const
56 {
57 	return resource;
58 }
59 
60 // Returns true on successful filter state update (valid enum parameter)
setMinFilter(GLenum filter)61 bool Texture::setMinFilter(GLenum filter)
62 {
63 	switch(filter)
64 	{
65 	case GL_NEAREST_MIPMAP_NEAREST:
66 	case GL_LINEAR_MIPMAP_NEAREST:
67 	case GL_NEAREST_MIPMAP_LINEAR:
68 	case GL_LINEAR_MIPMAP_LINEAR:
69 		if(getTarget() == GL_TEXTURE_EXTERNAL_OES)
70 		{
71 			return false;
72 		}
73 		// Fall through
74 	case GL_NEAREST:
75 	case GL_LINEAR:
76 		mMinFilter = filter;
77 		return true;
78 	default:
79 		return false;
80 	}
81 }
82 
83 // Returns true on successful filter state update (valid enum parameter)
setMagFilter(GLenum filter)84 bool Texture::setMagFilter(GLenum filter)
85 {
86 	switch(filter)
87 	{
88 	case GL_NEAREST:
89 	case GL_LINEAR:
90 		mMagFilter = filter;
91 		return true;
92 	default:
93 		return false;
94 	}
95 }
96 
97 // Returns true on successful wrap state update (valid enum parameter)
setWrapS(GLenum wrap)98 bool Texture::setWrapS(GLenum wrap)
99 {
100 	switch(wrap)
101 	{
102 	case GL_REPEAT:
103 	case GL_MIRRORED_REPEAT_OES:
104 		if(getTarget() == GL_TEXTURE_EXTERNAL_OES)
105 		{
106 			return false;
107 		}
108 		// Fall through
109 	case GL_CLAMP_TO_EDGE:
110 		mWrapS = wrap;
111 		return true;
112 	default:
113 		return false;
114 	}
115 }
116 
117 // Returns true on successful wrap state update (valid enum parameter)
setWrapT(GLenum wrap)118 bool Texture::setWrapT(GLenum wrap)
119 {
120 	switch(wrap)
121 	{
122 	case GL_REPEAT:
123 	case GL_MIRRORED_REPEAT_OES:
124 		if(getTarget() == GL_TEXTURE_EXTERNAL_OES)
125 		{
126 			return false;
127 		}
128 		// Fall through
129 	case GL_CLAMP_TO_EDGE:
130 		 mWrapT = wrap;
131 		 return true;
132 	default:
133 		return false;
134 	}
135 }
136 
137 // Returns true on successful max anisotropy update (valid anisotropy value)
setMaxAnisotropy(float textureMaxAnisotropy)138 bool Texture::setMaxAnisotropy(float textureMaxAnisotropy)
139 {
140 	textureMaxAnisotropy = std::min(textureMaxAnisotropy, MAX_TEXTURE_MAX_ANISOTROPY);
141 
142 	if(textureMaxAnisotropy < 1.0f)
143 	{
144 		return false;
145 	}
146 
147 	if(mMaxAnisotropy != textureMaxAnisotropy)
148 	{
149 		mMaxAnisotropy = textureMaxAnisotropy;
150 	}
151 
152 	return true;
153 }
154 
setGenerateMipmap(GLboolean enable)155 void Texture::setGenerateMipmap(GLboolean enable)
156 {
157 	generateMipmap = enable;
158 }
159 
setCropRect(GLint u,GLint v,GLint w,GLint h)160 void Texture::setCropRect(GLint u, GLint v, GLint w, GLint h)
161 {
162 	cropRectU = u;
163 	cropRectV = v;
164 	cropRectW = w;
165 	cropRectH = h;
166 }
167 
getMinFilter() const168 GLenum Texture::getMinFilter() const
169 {
170 	return mMinFilter;
171 }
172 
getMagFilter() const173 GLenum Texture::getMagFilter() const
174 {
175 	return mMagFilter;
176 }
177 
getWrapS() const178 GLenum Texture::getWrapS() const
179 {
180 	return mWrapS;
181 }
182 
getWrapT() const183 GLenum Texture::getWrapT() const
184 {
185 	return mWrapT;
186 }
187 
getMaxAnisotropy() const188 GLfloat Texture::getMaxAnisotropy() const
189 {
190 	return mMaxAnisotropy;
191 }
192 
getGenerateMipmap() const193 GLboolean Texture::getGenerateMipmap() const
194 {
195 	return generateMipmap;
196 }
197 
getCropRectU() const198 GLint Texture::getCropRectU() const
199 {
200 	return cropRectU;
201 }
202 
getCropRectV() const203 GLint Texture::getCropRectV() const
204 {
205 	return cropRectV;
206 }
207 
getCropRectW() const208 GLint Texture::getCropRectW() const
209 {
210 	return cropRectW;
211 }
212 
getCropRectH() const213 GLint Texture::getCropRectH() const
214 {
215 	return cropRectH;
216 }
217 
createSharedImage(GLenum target,unsigned int level)218 egl::Image *Texture::createSharedImage(GLenum target, unsigned int level)
219 {
220 	egl::Image *image = getRenderTarget(target, level);   // Increments reference count
221 
222 	if(image)
223 	{
224 		image->markShared();
225 	}
226 
227 	return image;
228 }
229 
setImage(GLenum format,GLenum type,GLint unpackAlignment,const void * pixels,egl::Image * image)230 void Texture::setImage(GLenum format, GLenum type, GLint unpackAlignment, const void *pixels, egl::Image *image)
231 {
232 	if(pixels && image)
233 	{
234 		gl::PixelStorageModes unpackParameters;
235 		unpackParameters.alignment = unpackAlignment;
236 		image->loadImageData(0, 0, 0, image->getWidth(), image->getHeight(), 1, format, type, unpackParameters, pixels);
237 	}
238 }
239 
setCompressedImage(GLsizei imageSize,const void * pixels,egl::Image * image)240 void Texture::setCompressedImage(GLsizei imageSize, const void *pixels, egl::Image *image)
241 {
242 	if(pixels && image && (imageSize > 0)) // imageSize's correlation to width and height is already validated with gl::ComputeCompressedSize() at the API level
243 	{
244 		image->loadCompressedData(0, 0, 0, image->getWidth(), image->getHeight(), 1, imageSize, pixels);
245 	}
246 }
247 
subImage(GLint xoffset,GLint yoffset,GLsizei width,GLsizei height,GLenum format,GLenum type,GLint unpackAlignment,const void * pixels,egl::Image * image)248 void Texture::subImage(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, GLint unpackAlignment, const void *pixels, egl::Image *image)
249 {
250 	if(!image)
251 	{
252 		return error(GL_INVALID_OPERATION);
253 	}
254 
255 	if(pixels)
256 	{
257 		gl::PixelStorageModes unpackParameters;
258 		unpackParameters.alignment = unpackAlignment;
259 		image->loadImageData(xoffset, yoffset, 0, width, height, 1, format, type, unpackParameters, pixels);
260 	}
261 }
262 
subImageCompressed(GLint xoffset,GLint yoffset,GLsizei width,GLsizei height,GLenum format,GLsizei imageSize,const void * pixels,egl::Image * image)263 void Texture::subImageCompressed(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const void *pixels, egl::Image *image)
264 {
265 	if(!image)
266 	{
267 		return error(GL_INVALID_OPERATION);
268 	}
269 
270 	if(pixels && (imageSize > 0)) // imageSize's correlation to width and height is already validated with gl::ComputeCompressedSize() at the API level
271 	{
272 		image->loadCompressedData(xoffset, yoffset, 0, width, height, 1, imageSize, pixels);
273 	}
274 }
275 
copy(egl::Image * source,const sw::Rect & sourceRect,GLenum destFormat,GLint xoffset,GLint yoffset,egl::Image * dest)276 bool Texture::copy(egl::Image *source, const sw::Rect &sourceRect, GLenum destFormat, GLint xoffset, GLint yoffset, egl::Image *dest)
277 {
278 	Device *device = getDevice();
279 
280 	sw::SliceRect destRect(xoffset, yoffset, xoffset + (sourceRect.x1 - sourceRect.x0), yoffset + (sourceRect.y1 - sourceRect.y0), 0);
281 	sw::SliceRect sourceSliceRect(sourceRect);
282 	bool success = device->stretchRect(source, &sourceSliceRect, dest, &destRect, false);
283 
284 	if(!success)
285 	{
286 		return error(GL_OUT_OF_MEMORY, false);
287 	}
288 
289 	return true;
290 }
291 
isMipmapFiltered() const292 bool Texture::isMipmapFiltered() const
293 {
294 	switch(mMinFilter)
295 	{
296 	case GL_NEAREST:
297 	case GL_LINEAR:
298 		return false;
299 	case GL_NEAREST_MIPMAP_NEAREST:
300 	case GL_LINEAR_MIPMAP_NEAREST:
301 	case GL_NEAREST_MIPMAP_LINEAR:
302 	case GL_LINEAR_MIPMAP_LINEAR:
303 		return true;
304 	default: UNREACHABLE(mMinFilter);
305 	}
306 
307 	return false;
308 }
309 
Texture2D(GLuint name)310 Texture2D::Texture2D(GLuint name) : Texture(name)
311 {
312 	for(int i = 0; i < IMPLEMENTATION_MAX_TEXTURE_LEVELS; i++)
313 	{
314 		image[i] = nullptr;
315 	}
316 
317 	mSurface = nullptr;
318 
319 	mColorbufferProxy = nullptr;
320 	mProxyRefs = 0;
321 }
322 
~Texture2D()323 Texture2D::~Texture2D()
324 {
325 	for(int i = 0; i < IMPLEMENTATION_MAX_TEXTURE_LEVELS; i++)
326 	{
327 		if(image[i])
328 		{
329 			image[i]->unbind(this);
330 			image[i] = nullptr;
331 		}
332 	}
333 
334 	if(mSurface)
335 	{
336 		mSurface->setBoundTexture(nullptr);
337 		mSurface = nullptr;
338 	}
339 
340 	mColorbufferProxy = nullptr;
341 }
342 
343 // We need to maintain a count of references to renderbuffers acting as
344 // proxies for this texture, so that we do not attempt to use a pointer
345 // to a renderbuffer proxy which has been deleted.
addProxyRef(const Renderbuffer * proxy)346 void Texture2D::addProxyRef(const Renderbuffer *proxy)
347 {
348 	mProxyRefs++;
349 }
350 
releaseProxy(const Renderbuffer * proxy)351 void Texture2D::releaseProxy(const Renderbuffer *proxy)
352 {
353 	if(mProxyRefs > 0)
354 	{
355 		mProxyRefs--;
356 	}
357 
358 	if(mProxyRefs == 0)
359 	{
360 		mColorbufferProxy = nullptr;
361 	}
362 }
363 
sweep()364 void Texture2D::sweep()
365 {
366 	int imageCount = 0;
367 
368 	for(int i = 0; i < IMPLEMENTATION_MAX_TEXTURE_LEVELS; i++)
369 	{
370 		if(image[i] && image[i]->isChildOf(this))
371 		{
372 			if(!image[i]->hasSingleReference())
373 			{
374 				return;
375 			}
376 
377 			imageCount++;
378 		}
379 	}
380 
381 	if(imageCount == referenceCount)
382 	{
383 		destroy();
384 	}
385 }
386 
getTarget() const387 GLenum Texture2D::getTarget() const
388 {
389 	return GL_TEXTURE_2D;
390 }
391 
getWidth(GLenum target,GLint level) const392 GLsizei Texture2D::getWidth(GLenum target, GLint level) const
393 {
394 	ASSERT(target == GL_TEXTURE_2D);
395 	return image[level] ? image[level]->getWidth() : 0;
396 }
397 
getHeight(GLenum target,GLint level) const398 GLsizei Texture2D::getHeight(GLenum target, GLint level) const
399 {
400 	ASSERT(target == GL_TEXTURE_2D);
401 	return image[level] ? image[level]->getHeight() : 0;
402 }
403 
getFormat(GLenum target,GLint level) const404 GLint Texture2D::getFormat(GLenum target, GLint level) const
405 {
406 	ASSERT(target == GL_TEXTURE_2D);
407 	return image[level] ? image[level]->getFormat() : GL_NONE;
408 }
409 
getTopLevel() const410 int Texture2D::getTopLevel() const
411 {
412 	ASSERT(isSamplerComplete());
413 	int level = 0;
414 
415 	while(level < IMPLEMENTATION_MAX_TEXTURE_LEVELS && image[level])
416 	{
417 		level++;
418 	}
419 
420 	return level - 1;
421 }
422 
setImage(GLint level,GLsizei width,GLsizei height,GLint internalformat,GLenum format,GLenum type,GLint unpackAlignment,const void * pixels)423 void Texture2D::setImage(GLint level, GLsizei width, GLsizei height, GLint internalformat, GLenum format, GLenum type, GLint unpackAlignment, const void *pixels)
424 {
425 	if(image[level])
426 	{
427 		image[level]->release();
428 	}
429 
430 	image[level] = egl::Image::create(this, width, height, internalformat);
431 
432 	if(!image[level])
433 	{
434 		return error(GL_OUT_OF_MEMORY);
435 	}
436 
437 	Texture::setImage(format, type, unpackAlignment, pixels, image[level]);
438 }
439 
bindTexImage(gl::Surface * surface)440 void Texture2D::bindTexImage(gl::Surface *surface)
441 {
442 	for(int level = 0; level < IMPLEMENTATION_MAX_TEXTURE_LEVELS; level++)
443 	{
444 		if(image[level])
445 		{
446 			image[level]->release();
447 			image[level] = nullptr;
448 		}
449 	}
450 
451 	image[0] = surface->getRenderTarget();
452 
453 	mSurface = surface;
454 	mSurface->setBoundTexture(this);
455 }
456 
releaseTexImage()457 void Texture2D::releaseTexImage()
458 {
459 	for(int level = 0; level < IMPLEMENTATION_MAX_TEXTURE_LEVELS; level++)
460 	{
461 		if(image[level])
462 		{
463 			image[level]->release();
464 			image[level] = nullptr;
465 		}
466 	}
467 }
468 
setCompressedImage(GLint level,GLenum format,GLsizei width,GLsizei height,GLsizei imageSize,const void * pixels)469 void Texture2D::setCompressedImage(GLint level, GLenum format, GLsizei width, GLsizei height, GLsizei imageSize, const void *pixels)
470 {
471 	if(image[level])
472 	{
473 		image[level]->release();
474 	}
475 
476 	image[level] = egl::Image::create(this, width, height, format);
477 
478 	if(!image[level])
479 	{
480 		return error(GL_OUT_OF_MEMORY);
481 	}
482 
483 	Texture::setCompressedImage(imageSize, pixels, image[level]);
484 }
485 
subImage(GLint level,GLint xoffset,GLint yoffset,GLsizei width,GLsizei height,GLenum format,GLenum type,GLint unpackAlignment,const void * pixels)486 void Texture2D::subImage(GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, GLint unpackAlignment, const void *pixels)
487 {
488 	Texture::subImage(xoffset, yoffset, width, height, format, type, unpackAlignment, pixels, image[level]);
489 }
490 
subImageCompressed(GLint level,GLint xoffset,GLint yoffset,GLsizei width,GLsizei height,GLenum format,GLsizei imageSize,const void * pixels)491 void Texture2D::subImageCompressed(GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const void *pixels)
492 {
493 	Texture::subImageCompressed(xoffset, yoffset, width, height, format, imageSize, pixels, image[level]);
494 }
495 
copyImage(GLint level,GLenum format,GLint x,GLint y,GLsizei width,GLsizei height,Framebuffer * source)496 void Texture2D::copyImage(GLint level, GLenum format, GLint x, GLint y, GLsizei width, GLsizei height, Framebuffer *source)
497 {
498 	if(image[level])
499 	{
500 		image[level]->release();
501 	}
502 
503 	image[level] = egl::Image::create(this, width, height, format);
504 
505 	if(!image[level])
506 	{
507 		return error(GL_OUT_OF_MEMORY);
508 	}
509 
510 	if(width != 0 && height != 0)
511 	{
512 		egl::Image *renderTarget = source->getRenderTarget();
513 
514 		if(!renderTarget)
515 		{
516 			ERR("Failed to retrieve the render target.");
517 			return error(GL_OUT_OF_MEMORY);
518 		}
519 
520 		sw::Rect sourceRect = {x, y, x + width, y + height};
521 		sourceRect.clip(0, 0, source->getColorbuffer()->getWidth(), source->getColorbuffer()->getHeight());
522 
523 		copy(renderTarget, sourceRect, format, 0, 0, image[level]);
524 
525 		renderTarget->release();
526 	}
527 }
528 
copySubImage(GLenum target,GLint level,GLint xoffset,GLint yoffset,GLint x,GLint y,GLsizei width,GLsizei height,Framebuffer * source)529 void Texture2D::copySubImage(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height, Framebuffer *source)
530 {
531 	if(!image[level])
532 	{
533 		return error(GL_INVALID_OPERATION);
534 	}
535 
536 	if(xoffset + width > image[level]->getWidth() || yoffset + height > image[level]->getHeight())
537 	{
538 		return error(GL_INVALID_VALUE);
539 	}
540 
541 	egl::Image *renderTarget = source->getRenderTarget();
542 
543 	if(!renderTarget)
544 	{
545 		ERR("Failed to retrieve the render target.");
546 		return error(GL_OUT_OF_MEMORY);
547 	}
548 
549 	sw::Rect sourceRect = {x, y, x + width, y + height};
550 	sourceRect.clip(0, 0, source->getColorbuffer()->getWidth(), source->getColorbuffer()->getHeight());
551 
552 	copy(renderTarget, sourceRect, image[level]->getFormat(), xoffset, yoffset, image[level]);
553 
554 	renderTarget->release();
555 }
556 
setSharedImage(egl::Image * sharedImage)557 void Texture2D::setSharedImage(egl::Image *sharedImage)
558 {
559 	sharedImage->addRef();
560 
561 	if(image[0])
562 	{
563 		image[0]->release();
564 	}
565 
566 	image[0] = sharedImage;
567 }
568 
569 // Tests for 2D texture sampling completeness. [OpenGL ES 2.0.24] section 3.8.2 page 85.
isSamplerComplete() const570 bool Texture2D::isSamplerComplete() const
571 {
572 	if(!image[0])
573 	{
574 		return false;
575 	}
576 
577 	GLsizei width = image[0]->getWidth();
578 	GLsizei height = image[0]->getHeight();
579 
580 	if(width <= 0 || height <= 0)
581 	{
582 		return false;
583 	}
584 
585 	if(isMipmapFiltered())
586 	{
587 		if(!generateMipmap && !isMipmapComplete())
588 		{
589 			return false;
590 		}
591 	}
592 
593 	return true;
594 }
595 
596 // Tests for 2D texture (mipmap) completeness. [OpenGL ES 2.0.24] section 3.7.10 page 81.
isMipmapComplete() const597 bool Texture2D::isMipmapComplete() const
598 {
599 	GLsizei width = image[0]->getWidth();
600 	GLsizei height = image[0]->getHeight();
601 
602 	int q = log2(std::max(width, height));
603 
604 	for(int level = 1; level <= q; level++)
605 	{
606 		if(!image[level])
607 		{
608 			return false;
609 		}
610 
611 		if(image[level]->getFormat() != image[0]->getFormat())
612 		{
613 			return false;
614 		}
615 
616 		if(image[level]->getWidth() != std::max(1, width >> level))
617 		{
618 			return false;
619 		}
620 
621 		if(image[level]->getHeight() != std::max(1, height >> level))
622 		{
623 			return false;
624 		}
625 	}
626 
627 	return true;
628 }
629 
isCompressed(GLenum target,GLint level) const630 bool Texture2D::isCompressed(GLenum target, GLint level) const
631 {
632 	return IsCompressed(getFormat(target, level));
633 }
634 
isDepth(GLenum target,GLint level) const635 bool Texture2D::isDepth(GLenum target, GLint level) const
636 {
637 	return IsDepthTexture(getFormat(target, level));
638 }
639 
generateMipmaps()640 void Texture2D::generateMipmaps()
641 {
642 	if(!image[0])
643 	{
644 		return;   // FIXME: error?
645 	}
646 
647 	unsigned int q = log2(std::max(image[0]->getWidth(), image[0]->getHeight()));
648 
649 	for(unsigned int i = 1; i <= q; i++)
650 	{
651 		if(image[i])
652 		{
653 			image[i]->release();
654 		}
655 
656 		image[i] = egl::Image::create(this, std::max(image[0]->getWidth() >> i, 1), std::max(image[0]->getHeight() >> i, 1), image[0]->getFormat());
657 
658 		if(!image[i])
659 		{
660 			return error(GL_OUT_OF_MEMORY);
661 		}
662 
663 		getDevice()->stretchRect(image[i - 1], 0, image[i], 0, true);
664 	}
665 }
666 
autoGenerateMipmaps()667 void Texture2D::autoGenerateMipmaps()
668 {
669 	if(generateMipmap && image[0]->hasDirtyContents())
670 	{
671 		generateMipmaps();
672 		image[0]->markContentsClean();
673 	}
674 }
675 
getImage(unsigned int level)676 egl::Image *Texture2D::getImage(unsigned int level)
677 {
678 	return image[level];
679 }
680 
getRenderbuffer(GLenum target,GLint level)681 Renderbuffer *Texture2D::getRenderbuffer(GLenum target, GLint level)
682 {
683 	if(target != GL_TEXTURE_2D)
684 	{
685 		return error(GL_INVALID_OPERATION, (Renderbuffer*)nullptr);
686 	}
687 
688 	if(!mColorbufferProxy)
689 	{
690 		mColorbufferProxy = new Renderbuffer(name, new RenderbufferTexture2D(this, level));
691 	}
692 	else
693 	{
694 		mColorbufferProxy->setLevel(level);
695 	}
696 
697 	return mColorbufferProxy;
698 }
699 
getRenderTarget(GLenum target,unsigned int level)700 egl::Image *Texture2D::getRenderTarget(GLenum target, unsigned int level)
701 {
702 	ASSERT(target == GL_TEXTURE_2D);
703 	ASSERT(level < IMPLEMENTATION_MAX_TEXTURE_LEVELS);
704 
705 	if(image[level])
706 	{
707 		image[level]->addRef();
708 	}
709 
710 	return image[level];
711 }
712 
isShared(GLenum target,unsigned int level) const713 bool Texture2D::isShared(GLenum target, unsigned int level) const
714 {
715 	ASSERT(target == GL_TEXTURE_2D);
716 	ASSERT(level < IMPLEMENTATION_MAX_TEXTURE_LEVELS);
717 
718 	if(mSurface)   // Bound to an EGLSurface
719 	{
720 		return true;
721 	}
722 
723 	if(!image[level])
724 	{
725 		return false;
726 	}
727 
728 	return image[level]->isShared();
729 }
730 
TextureExternal(GLuint name)731 TextureExternal::TextureExternal(GLuint name) : Texture2D(name)
732 {
733 	mMinFilter = GL_LINEAR;
734 	mMagFilter = GL_LINEAR;
735 	mWrapS = GL_CLAMP_TO_EDGE;
736 	mWrapT = GL_CLAMP_TO_EDGE;
737 }
738 
~TextureExternal()739 TextureExternal::~TextureExternal()
740 {
741 }
742 
getTarget() const743 GLenum TextureExternal::getTarget() const
744 {
745 	return GL_TEXTURE_EXTERNAL_OES;
746 }
747 
748 }
749 
createBackBuffer(int width,int height,sw::Format format,int multiSampleDepth)750 egl::Image *createBackBuffer(int width, int height, sw::Format format, int multiSampleDepth)
751 {
752 	if(width > es1::IMPLEMENTATION_MAX_RENDERBUFFER_SIZE || height > es1::IMPLEMENTATION_MAX_RENDERBUFFER_SIZE)
753 	{
754 		ERR("Invalid parameters: %dx%d", width, height);
755 		return nullptr;
756 	}
757 
758 	GLenum internalformat = sw2es::ConvertBackBufferFormat(format);
759 
760 	return egl::Image::create(width, height, internalformat, multiSampleDepth, false);
761 }
762 
createDepthStencil(int width,int height,sw::Format format,int multiSampleDepth)763 egl::Image *createDepthStencil(int width, int height, sw::Format format, int multiSampleDepth)
764 {
765 	if(width > es1::IMPLEMENTATION_MAX_RENDERBUFFER_SIZE || height > es1::IMPLEMENTATION_MAX_RENDERBUFFER_SIZE)
766 	{
767 		ERR("Invalid parameters: %dx%d", width, height);
768 		return nullptr;
769 	}
770 
771 	bool lockable = true;
772 
773 	switch(format)
774 	{
775 //	case sw::FORMAT_D15S1:
776 	case sw::FORMAT_D24S8:
777 	case sw::FORMAT_D24X8:
778 //	case sw::FORMAT_D24X4S4:
779 	case sw::FORMAT_D24FS8:
780 	case sw::FORMAT_D32:
781 	case sw::FORMAT_D16:
782 		lockable = false;
783 		break;
784 //	case sw::FORMAT_S8_LOCKABLE:
785 //	case sw::FORMAT_D16_LOCKABLE:
786 	case sw::FORMAT_D32F_LOCKABLE:
787 //	case sw::FORMAT_D32_LOCKABLE:
788 	case sw::FORMAT_DF24S8:
789 	case sw::FORMAT_DF16S8:
790 		lockable = true;
791 		break;
792 	default:
793 		UNREACHABLE(format);
794 	}
795 
796 	GLenum internalformat = sw2es::ConvertDepthStencilFormat(format);
797 
798 	egl::Image *surface = egl::Image::create(width, height, internalformat, multiSampleDepth, lockable);
799 
800 	if(!surface)
801 	{
802 		ERR("Out of memory");
803 		return nullptr;
804 	}
805 
806 	return surface;
807 }
808