Esempio n. 1
0
bool IndependentBlocks::splitExitBlock(Region *R) {
  // Split the exit BB to place the load instruction of escaped users.
  BasicBlock *ExitBB = R->getExit();
  Region *ExitRegion = RI->getRegionFor(ExitBB);

  if (ExitBB != ExitRegion->getEntry())
    return false;

  BasicBlock *NewExit = createSingleExitEdge(R, this);

  std::vector<Region *> toUpdate;
  toUpdate.push_back(R);

  while (!toUpdate.empty()) {
    Region *Reg = toUpdate.back();
    toUpdate.pop_back();

    for (Region::iterator I = Reg->begin(), E = Reg->end(); I != E; ++I) {
      Region *SubR = *I;

      if (SubR->getExit() == ExitBB)
        toUpdate.push_back(SubR);
    }

    Reg->replaceExit(NewExit);
  }

  RI->setRegionFor(NewExit, R->getParent());
  return true;
}
Esempio n. 2
0
  // Print the cluster of the subregions. This groups the single basic blocks
  // and adds a different background color for each group.
  static void printRegionCluster(const Region &R, GraphWriter<RegionInfo *> &GW,
                                 unsigned depth = 0) {
    raw_ostream &O = GW.getOStream();
    O.indent(2 * depth) << "subgraph cluster_" << static_cast<const void*>(&R)
      << " {\n";
    O.indent(2 * (depth + 1)) << "label = \"\";\n";

    if (!onlySimpleRegions || R.isSimple()) {
      O.indent(2 * (depth + 1)) << "style = filled;\n";
      O.indent(2 * (depth + 1)) << "color = "
        << ((R.getDepth() * 2 % 12) + 1) << "\n";

    } else {
      O.indent(2 * (depth + 1)) << "style = solid;\n";
      O.indent(2 * (depth + 1)) << "color = "
        << ((R.getDepth() * 2 % 12) + 2) << "\n";
    }

    for (Region::const_iterator RI = R.begin(), RE = R.end(); RI != RE; ++RI)
      printRegionCluster(**RI, GW, depth + 1);

    const RegionInfo &RI = *static_cast<const RegionInfo*>(R.getRegionInfo());

    for (auto *BB : R.blocks())
      if (RI.getRegionFor(BB) == &R)
        O.indent(2 * (depth + 1)) << "Node"
          << static_cast<const void*>(RI.getTopLevelRegion()->getBBNode(BB))
          << ";\n";

    O.indent(2 * depth) << "}\n";
  }
Esempio n. 3
0
    void nextStep(
        GridType *grid,
        const Region<Topology::DIM>& validRegion,
        const CoordType& globalDimensions,
        unsigned step,
        SteererEvent event,
        std::size_t rank,
        bool lastCall,
        SteererFeedback *feedback)
    {
        if (waterAvailable && (trigger->averageTemperature() > 250)) {
            std::cout << "WARNING---------------------------------------------------\n"
                      << "WARNING: initiating rain at time step " << step << "\n"
                      << "WARNING---------------------------------------------------\n";

            for (Region<Topology::DIM>::Iterator i = validRegion.begin();
                 i != validRegion.end();
                 ++i) {
                BushFireCell cell = grid->get(*i);
                if ((cell.fuel > 0) && (cell.temperature > 0.0001)) {
                    cell.humidity += 0.5;
                }
                grid->set(*i, cell);
            }

            if (lastCall) {
                waterAvailable = 0;
            }
        }
    }
Esempio n. 4
0
int Board::count(const Region& ss, const Piece &value) const {
    register int result = 0;
    for (auto s = ss.begin(); s != ss.end(); s++)
        if (at(s->file(),s->rank()) == value)
            result++;
    return result;
}
Esempio n. 5
0
void polly::simplifyRegion(Scop *S, Pass *P) {
  Region *R = &S->getRegion();

  // Create single entry edge if the region has multiple entry edges.
  if (!R->getEnteringBlock()) {
    BasicBlock *OldEntry = R->getEntry();
    BasicBlock *NewEntry = SplitBlock(OldEntry, OldEntry->begin(), P);

    for (Scop::iterator SI = S->begin(), SE = S->end(); SI != SE; ++SI)
      if ((*SI)->getBasicBlock() == OldEntry) {
        (*SI)->setBasicBlock(NewEntry);
        break;
      }

    R->replaceEntryRecursive(NewEntry);
  }

  // Create single exit edge if the region has multiple exit edges.
  if (!R->getExitingBlock()) {
    BasicBlock *NewExit = createSingleExitEdge(R, P);

    for (Region::const_iterator RI = R->begin(), RE = R->end(); RI != RE; ++RI)
      (*RI)->replaceExitRecursive(NewExit);
  }
}
Esempio n. 6
0
void ji_move_region(const Region& region, int dx, int dy)
{
  size_t nrects = region.size();

  // Blit directly screen to screen.
  if (is_linear_bitmap(ji_screen) && nrects == 1) {
    Rect rc = region[0];
    blit(ji_screen, ji_screen, rc.x, rc.y, rc.x+dx, rc.y+dy, rc.w, rc.h);
  }
  // Blit saving areas and copy them.
  else if (nrects > 1) {
    std::vector<BITMAP*> images(nrects);
    Region::const_iterator it, begin=region.begin(), end=region.end();
    BITMAP* bmp;
    int c;

    for (c=0, it=begin; it != end; ++it, ++c) {
      const Rect& rc = *it;
      bmp = create_bitmap(rc.w, rc.h);
      blit(ji_screen, bmp, rc.x, rc.y, 0, 0, bmp->w, bmp->h);
      images[c] = bmp;
    }

    for (c=0, it=begin; it != end; ++it, ++c) {
      const Rect& rc = *it;
      bmp = images[c];
      blit(bmp, ji_screen, 0, 0, rc.x+dx, rc.y+dy, bmp->w, bmp->h);
      destroy_bitmap(bmp);
    }
  }
}
Esempio n. 7
0
TEST(Region, Iterators)
{
  Region a;
  a.createUnion(a, Region(Rect(0, 0, 32, 64)));
  a.createUnion(a, Region(Rect(0, 0, 64, 32)));
  int c = 0;
  for (Region::iterator it=a.begin(), end=a.end(); it!=end; ++it) {
    ++c;
  }
  EXPECT_EQ(2, c);

  c = 0;
  for (Region::const_iterator it=a.begin(), end=a.end(); it!=end; ++it) {
    ++c;
  }
  EXPECT_EQ(2, c);
}
Esempio n. 8
0
/*
 * Clear Region implementation for C2D/MDP versions.
 *
 * @param: region to be cleared
 * @param: EGL Display
 * @param: EGL Surface
 *
 * @return 0 on success
 */
int qcomuiClearRegion(Region region, EGLDisplay dpy, EGLSurface sur)
{
    int ret = 0;

    if (-1 == sCompositionType) {
        sCompositionType = getCompositionType();
    }

    if ((COMPOSITION_TYPE_MDP != sCompositionType) &&
        (COMPOSITION_TYPE_C2D != sCompositionType) &&
#ifdef USE_MDP3
        (COMPOSITION_TYPE_DYN != sCompositionType) &&
#endif
        (COMPOSITION_TYPE_CPU != sCompositionType)) {
        // For non CPU/C2D/MDP composition, return an error, so that SF can use
        // the GPU to draw the wormhole.
        return -1;
    }

    android_native_buffer_t *renderBuffer = (android_native_buffer_t *)
                                        eglGetRenderBufferANDROID(dpy, sur);
    if (!renderBuffer) {
        LOGE("%s: eglGetRenderBufferANDROID returned NULL buffer",
            __FUNCTION__);
            return -1;
    }
    private_handle_t *fbHandle = (private_handle_t *)renderBuffer->handle;
    if(!fbHandle) {
        LOGE("%s: Framebuffer handle is NULL", __FUNCTION__);
        return -1;
    }

    int bytesPerPixel = 4;
    if (HAL_PIXEL_FORMAT_RGB_565 == fbHandle->format) {
        bytesPerPixel = 2;
    }

    Region::const_iterator it = region.begin();
    Region::const_iterator const end = region.end();
    const int32_t stride = renderBuffer->stride*bytesPerPixel;
    while (it != end) {
        const Rect& r = *it++;
        uint8_t* dst = (uint8_t*) fbHandle->base +
                       (r.left + r.top*renderBuffer->stride)*bytesPerPixel;
        int w = r.width()*bytesPerPixel;
        int h = r.height();
        do {
            if(4 == bytesPerPixel)
                android_memset32((uint32_t*)dst, 0, w);
            else
                android_memset16((uint16_t*)dst, 0, w);
            dst += stride;
        } while(--h);
    }
    return 0;
}
//40641 for 3D
void LayerBase::drawNormal(const Region& clip ,uint32_t fbHeight ,uint8_t eType ) const
{
	struct TexCoords {
        				GLfloat u;
      					GLfloat v;
   						};			 
	TexCoords texCoords[4];
	if(ISurfaceComposer::eLayerSideBySide == eType)
		{
			texCoords[0].u = 0; 
			texCoords[0].v = 1; 
			texCoords[1].u = 0; 
			texCoords[1].v = 0;
			texCoords[2].u = 0.5;
			texCoords[2].v = 0;
			texCoords[3].u = 0.5;
			texCoords[3].v = 1;
		
		}
	else if (ISurfaceComposer::eLayerTopAndBottom == eType)
		{
			texCoords[0].v = 0.5; 
			texCoords[1].u = 0; 
			texCoords[1].v = 0;
			texCoords[2].u = 1;
			texCoords[2].v = 0;
			texCoords[3].u = 1;
			texCoords[3].v = 0.5;
		}
	else 
		{
			texCoords[0].u = 0; 
			texCoords[0].v = 1; 
			texCoords[1].u = 0; 
			texCoords[1].v = 0;
			texCoords[2].u = 1;
			texCoords[2].v = 0;
			texCoords[3].u = 1;
			texCoords[3].v = 1;
		}
	
			glEnableClientState(GL_TEXTURE_COORD_ARRAY);
			glVertexPointer(2, GL_FLOAT, 0, mVertices);
			glTexCoordPointer(2, GL_FLOAT, 0, texCoords);
			Region::const_iterator it = clip.begin();
			Region::const_iterator const end = clip.end();		
			while (it != end) {
				const Rect& r = *it++;				
				const GLint sy = fbHeight - (r.top + r.height());
				glScissor((r.left), sy, r.width(), r.height()); 
				glDrawArrays(GL_TRIANGLE_FAN, 0, 4);   
			}

}
Esempio n. 10
0
int CBUtils::qcomuiClearRegion(Region region, EGLDisplay dpy){

    int ret = 0;
    int compositionType = QCCompositionType::getInstance().getCompositionType();
    if ((compositionType == COMPOSITION_TYPE_GPU) || sGPUlayerpresent) {
        //return ERROR when GPU composition is used or any layer is flagged
        //for GPU composition.
        return -1;
    }



    android_native_buffer_t *renderBuffer =
          qdutils::eglHandles::getInstance().getAndroidNativeRenderBuffer(dpy);

    if (!renderBuffer) {
        ALOGE("%s: eglGetRenderBufferANDROID returned NULL buffer",
             __FUNCTION__);
        return -1;
    }
   private_handle_t *fbHandle = (private_handle_t *)renderBuffer->handle;
    if(!fbHandle) {
        ALOGE("%s: Framebuffer handle is NULL", __FUNCTION__);
        return -1;
    }

    int bytesPerPixel = 4;
    if (HAL_PIXEL_FORMAT_RGB_565 == fbHandle->format) {
        bytesPerPixel = 2;
    }

    Region::const_iterator it = region.begin();
    Region::const_iterator const end = region.end();
    const int32_t stride = renderBuffer->stride*bytesPerPixel;
    while (it != end) {
        const Rect& r = *it++;
        uint8_t* dst = (uint8_t*) fbHandle->base +
            (r.left + r.top*renderBuffer->stride)*bytesPerPixel;
        int w = r.width()*bytesPerPixel;
        int h = r.height();

        do {
            if(4 == bytesPerPixel){
                android_memset32((uint32_t*)dst, 0, w);
            } else {
                android_memset16((uint16_t*)dst, 0, w);
            }
            dst += stride;
        } while(--h);
    }
    return 0;
}
Esempio n. 11
0
    AdjacencyPtr getAdjacency(const Region<1>& region) const
    {
	AdjacencyPtr adjacency(new RegionBasedAdjacency());

	for (Region<1>::Iterator i = region.begin(); i != region.end(); ++i) {
            std::vector<int> neighbors = genNeighborList(i->x());
            for (auto&& neighbor: neighbors) {
                adjacency->insert(i->x(), neighbor);
            }
	}

	return adjacency;
    }
Esempio n. 12
0
void move_region(Manager* manager, const Region& region, int dx, int dy)
{
  she::System* system = she::instance();
  she::Display* display = Manager::getDefault()->getDisplay();
  ASSERT(display);
  if (!display)
    return;

  she::ScopedSurfaceLock lock(display->getSurface());
  std::size_t nrects = region.size();

  // Blit directly screen to screen.
  if (nrects == 1) {
    gfx::Rect rc = region[0];
    lock->scrollTo(rc, dx, dy);

    rc.offset(dx, dy);
    Manager::getDefault()->dirtyRect(rc);

  }
  // Blit saving areas and copy them.
  else if (nrects > 1) {
    std::vector<she::Surface*> images(nrects);
    Region::const_iterator it, begin=region.begin(), end=region.end();
    she::Surface* sur;
    int c;

    for (c=0, it=begin; it != end; ++it, ++c) {
      const Rect& rc = *it;
      sur = system->createSurface(rc.w, rc.h);
      {
        she::ScopedSurfaceLock surlock(sur);
        lock->blitTo(surlock, rc.x, rc.y, 0, 0, rc.w, rc.h);
      }
      images[c] = sur;
    }

    for (c=0, it=begin; it != end; ++it, ++c) {
      gfx::Rect rc((*it).x+dx, (*it).y+dy, (*it).w, (*it).h);
      sur = images[c];
      {
        she::ScopedSurfaceLock surlock(sur);
        surlock->blitTo(lock, 0, 0, rc.x, rc.y, rc.w, rc.h);
        manager->dirtyRect(rc);
      }
      sur->dispose();
    }
  }
}
Esempio n. 13
0
void Region::replaceExitRecursive(BasicBlock *NewExit) {
  std::vector<Region *> RegionQueue;
  BasicBlock *OldExit = getExit();

  RegionQueue.push_back(this);
  while (!RegionQueue.empty()) {
    Region *R = RegionQueue.back();
    RegionQueue.pop_back();

    R->replaceExit(NewExit);
    for (Region::const_iterator RI = R->begin(), RE = R->end(); RI != RE; ++RI)
      if ((*RI)->getExit() == OldExit)
        RegionQueue.push_back(*RI);
  }
}
/**
 * Creates a new region with the same data as the argument, but divides rectangles as necessary to
 * remove T-Junctions
 *
 * Note: the output will not necessarily be a very efficient representation of the region, since it
 * may be that a triangle-based approach would generate significantly simpler geometry
 */
Region Region::createTJunctionFreeRegion(const Region& r) {
    if (r.isEmpty()) return r;
    if (r.isRect()) return r;

    Vector<Rect> reversed;
    reverseRectsResolvingJunctions(r.begin(), r.end(), reversed, direction_RTL);

    Region outputRegion;
    reverseRectsResolvingJunctions(reversed.begin(), reversed.end(),
            outputRegion.mStorage, direction_LTR);
    outputRegion.mStorage.add(r.getBounds()); // to make region valid, mStorage must end with bounds

#if VALIDATE_REGIONS
    validate(outputRegion, "T-Junction free region");
#endif

    return outputRegion;
}
Region Transform::transform(const Region& reg) const
{
    Region out;
    if (CC_UNLIKELY(type() > TRANSLATE)) {
        if (CC_LIKELY(preserveRects())) {
            Region::const_iterator it = reg.begin();
            Region::const_iterator const end = reg.end();
            while (it != end) {
                out.orSelf(transform(*it++));
            }
        } else {
            out.set(transform(reg.bounds()));
        }
    } else {
        int xpos = floorf(tx() + 0.5f);
        int ypos = floorf(ty() + 0.5f);
        out = reg.translate(xpos, ypos);
    }
    return out;
}
Esempio n. 16
0
void LayerBase::drawRegion(const Region& reg) const
{
    Region::const_iterator it = reg.begin();
    Region::const_iterator const end = reg.end();
    if (it != end) {
        Rect r;
        const DisplayHardware& hw(graphicPlane(0).displayHardware());
        const int32_t fbWidth  = hw.getWidth();
        const int32_t fbHeight = hw.getHeight();
        const GLshort vertices[][2] = { { 0, 0 }, { fbWidth, 0 }, 
                { fbWidth, fbHeight }, { 0, fbHeight }  };
        glVertexPointer(2, GL_SHORT, 0, vertices);
        while (it != end) {
            const Rect& r = *it++;
            const GLint sy = fbHeight - (r.top + r.height());
            glScissor(r.left, sy, r.width(), r.height());
            glDrawArrays(GL_TRIANGLE_FAN, 0, 4); 
        }
    }
}
Esempio n. 17
0
    AdjacencyPtr getAdjacency(const Region<1>& region) const
    {
        AdjacencyPtr adjacency(new RegionBasedAdjacency);

        for (Region<1>::Iterator i = region.begin(); i != region.end(); ++i) {
            int id = i->x();
            int x = id % width();
            int y = id / width();
            int west = y * width() + (width() + x - 1) % width();
            int east = y * width() + (width() + x + 1) % width();
            int north = ((height() + y - 1) % height()) * width() + x;
            int south = ((height() + y + 1) % height()) * width() + x;
            adjacency->insert(id, west);
            adjacency->insert(id, east);
            adjacency->insert(id, north);
            adjacency->insert(id, south);
        }

        return adjacency;
    }
Esempio n. 18
0
bool Region::validate(const Region& reg, const char* name)
{
    bool result = true;
    const_iterator cur = reg.begin();
    const_iterator const tail = reg.end();
    const_iterator prev = cur++;
    Rect b(*prev);
    while (cur != tail) {
        b.left   = b.left   < cur->left   ? b.left   : cur->left;
        b.top    = b.top    < cur->top    ? b.top    : cur->top;
        b.right  = b.right  > cur->right  ? b.right  : cur->right;
        b.bottom = b.bottom > cur->bottom ? b.bottom : cur->bottom;
        if (cur->top == prev->top) {
            if (cur->bottom != prev->bottom) {
                LOGE("%s: invalid span %p", name, cur);
                result = false;
            } else if (cur->left < prev->right) {
                LOGE("%s: spans overlap horizontally prev=%p, cur=%p",
                        name, prev, cur);
                result = false;
            }
        } else if (cur->top < prev->bottom) {
            LOGE("%s: spans overlap vertically prev=%p, cur=%p",
                    name, prev, cur);
            result = false;
        }
        prev = cur;
        cur++;
    }
    if (b != reg.getBounds()) {
        result = false;
        LOGE("%s: invalid bounds [%d,%d,%d,%d] vs. [%d,%d,%d,%d]", name,
                b.left, b.top, b.right, b.bottom,
                reg.getBounds().left, reg.getBounds().top, 
                reg.getBounds().right, reg.getBounds().bottom);
    }
    if (result == false) {
        reg.dump(name);
    }
    return result;
}
Esempio n. 19
0
void FGLWindowSurface::copyBlt(
	android_native_buffer_t *dst, void *dst_vaddr,
	android_native_buffer_t *src, const void *src_vaddr,
	const Region& clip)
{
	// NOTE: dst and src must be the same format
	Region::const_iterator cur = clip.begin();
	Region::const_iterator end = clip.end();

	const size_t bpp = getBpp(src->format);
	const size_t dbpr = dst->stride * bpp;
	const size_t sbpr = src->stride * bpp;

	const uint8_t *const src_bits = (const uint8_t *)src_vaddr;
	uint8_t       *const dst_bits = (uint8_t       *)dst_vaddr;

	while (cur != end) {
		const Rect& r(*cur++);
		ssize_t w = r.right - r.left;
		ssize_t h = r.bottom - r.top;

		if (w <= 0 || h<=0) continue;

		size_t size = w * bpp;
		const uint8_t *s = src_bits + (r.left + src->stride * r.top) * bpp;
		uint8_t       *d = dst_bits + (r.left + dst->stride * r.top) * bpp;

		if (dbpr==sbpr && size==sbpr) {
			size *= h;
			h = 1;
		}

		do {
			memcpy(d, s, size);
			d += dbpr;
			s += sbpr;
		} while (--h > 0);
	}
}
Esempio n. 20
0
void LayerBase::clearWithOpenGL(const Region& clip, GLclampf red,
                                GLclampf green, GLclampf blue,
                                GLclampf alpha) const
{
    const DisplayHardware& hw(graphicPlane(0).displayHardware());
    const uint32_t fbHeight = hw.getHeight();
    glColor4f(red,green,blue,alpha);

    glDisable(GL_TEXTURE_EXTERNAL_OES);
    glDisable(GL_TEXTURE_2D);
    glDisable(GL_BLEND);

    Region::const_iterator it = clip.begin();
    Region::const_iterator const end = clip.end();
    glEnable(GL_SCISSOR_TEST);
    glVertexPointer(2, GL_FLOAT, 0, mVertices);
    while (it != end) {
        const Rect& r = *it++;
        const GLint sy = fbHeight - (r.top + r.height());
        glScissor(r.left, sy, r.width(), r.height());
        glDrawArrays(GL_TRIANGLE_FAN, 0, 4); 
    }
}
Esempio n. 21
0
void Region::boolean_operation(int op, Region& dst,
        const Region& lhs,
        const Region& rhs, int dx, int dy)
{
#if VALIDATE_REGIONS
    validate(lhs, "boolean_operation (before): lhs");
    validate(rhs, "boolean_operation (before): rhs");
    validate(dst, "boolean_operation (before): dst");
#endif

    size_t lhs_count;
    Rect const * const lhs_rects = lhs.getArray(&lhs_count);

    size_t rhs_count;
    Rect const * const rhs_rects = rhs.getArray(&rhs_count);

    region_operator<Rect>::region lhs_region(lhs_rects, lhs_count);
    region_operator<Rect>::region rhs_region(rhs_rects, rhs_count, dx, dy);
    region_operator<Rect> operation(op, lhs_region, rhs_region);
    { // scope for rasterizer (dtor has side effects)
        rasterizer r(dst);
        operation(r);
    }

#if VALIDATE_REGIONS
    validate(lhs, "boolean_operation: lhs");
    validate(rhs, "boolean_operation: rhs");
    validate(dst, "boolean_operation: dst");
#endif

#if VALIDATE_WITH_CORECG
    SkRegion sk_lhs;
    SkRegion sk_rhs;
    SkRegion sk_dst;
    
    for (size_t i=0 ; i<lhs_count ; i++)
        sk_lhs.op(
                lhs_rects[i].left   + dx,
                lhs_rects[i].top    + dy,
                lhs_rects[i].right  + dx,
                lhs_rects[i].bottom + dy,
                SkRegion::kUnion_Op);
    
    for (size_t i=0 ; i<rhs_count ; i++)
        sk_rhs.op(
                rhs_rects[i].left   + dx,
                rhs_rects[i].top    + dy,
                rhs_rects[i].right  + dx,
                rhs_rects[i].bottom + dy,
                SkRegion::kUnion_Op);
 
    const char* name = "---";
    SkRegion::Op sk_op;
    switch (op) {
        case op_or: sk_op = SkRegion::kUnion_Op; name="OR"; break;
        case op_and: sk_op = SkRegion::kIntersect_Op; name="AND"; break;
        case op_nand: sk_op = SkRegion::kDifference_Op; name="NAND"; break;
    }
    sk_dst.op(sk_lhs, sk_rhs, sk_op);

    if (sk_dst.isEmpty() && dst.isEmpty())
        return;
    
    bool same = true;
    Region::const_iterator head = dst.begin();
    Region::const_iterator const tail = dst.end();
    SkRegion::Iterator it(sk_dst);
    while (!it.done()) {
        if (head != tail) {
            if (
                    head->left != it.rect().fLeft ||     
                    head->top != it.rect().fTop ||     
                    head->right != it.rect().fRight ||     
                    head->bottom != it.rect().fBottom
            ) {
                same = false;
                break;
            }
        } else {
            same = false;
            break;
        }
        head++;
        it.next();
    }
    
    if (head != tail) {
        same = false;
    }
    
    if(!same) {
        LOGD("---\nregion boolean %s failed", name);
        lhs.dump("lhs");
        rhs.dump("rhs");
        dst.dump("dst");
        LOGD("should be");
        SkRegion::Iterator it(sk_dst);
        while (!it.done()) {
            LOGD("    [%3d, %3d, %3d, %3d]",
                it.rect().fLeft,
                it.rect().fTop,
                it.rect().fRight,
                it.rect().fBottom);
            it.next();
        }
    }
#endif
}
Esempio n. 22
0
void LayerBase::drawTopAndBottom(const Region& clip ,uint32_t fbHeight ,uint8_t eType ) const
{
				struct TexCoords {
							GLfloat u;
							GLfloat v;
							};			 
				TexCoords texCoords[4];
				GLfloat mVerticesCopy1[4][2];
				GLfloat mVerticesCopy[4][2]; 
				mVerticesCopy1[0][0] = mVertices[0][0]; 
				mVerticesCopy1[0][1] = mVertices[0][1]; 
				mVerticesCopy1[1][0] = mVertices[1][0]; 
				mVerticesCopy1[1][1] = mVertices[1][1]; 
				mVerticesCopy1[2][0] = mVertices[2][0]; 
				mVerticesCopy1[2][1] = mVertices[2][1]; 
				mVerticesCopy1[3][0] = mVertices[3][0]; 
				mVerticesCopy1[3][1] = mVertices[3][1]; 	
				for (size_t i=0 ; i<4 ; i++){
					mVerticesCopy1[i][1] /= 2;						
				}
				mVerticesCopy[0][0] = mVerticesCopy1[0][0] ; 
				mVerticesCopy[0][1] = mVerticesCopy1[0][1]+(fbHeight/2); 
				mVerticesCopy[1][0] = mVerticesCopy1[1][0] ; 
				mVerticesCopy[1][1] = mVerticesCopy1[1][1]+(fbHeight/2); 
				mVerticesCopy[2][0] = mVerticesCopy1[2][0] ; 
				mVerticesCopy[2][1] = mVerticesCopy1[2][1]+(fbHeight/2); 
				mVerticesCopy[3][0] = mVerticesCopy1[3][0]; 
				mVerticesCopy[3][1] = mVerticesCopy1[3][1]+(fbHeight/2);
						//3d surface
				
				if(ISurfaceComposer::eLayerTopAndBottom == eType)
				{
					//draw 3D buttom to  FB buttom
							
					texCoords[0].u = 0; 
					texCoords[0].v = 0.5; 
					texCoords[1].u = 0; 
					texCoords[1].v = 0;
					texCoords[2].u = 1;
					texCoords[2].v = 0;
					texCoords[3].u = 1;
					texCoords[3].v = 0.5;
					glEnableClientState(GL_TEXTURE_COORD_ARRAY);			
					glVertexPointer(2, GL_FLOAT, 0, mVerticesCopy1);
					glTexCoordPointer(2, GL_FLOAT, 0, texCoords);
					Region::const_iterator it = clip.begin();
					Region::const_iterator const end = clip.end();			
					while (it != end) {
						const Rect& r = *it++;		
						const GLint sy = fbHeight - (r.top + r.height());			
						glScissor(r.left, sy/2, r.width(), r.height()/2);			
						glDrawArrays(GL_TRIANGLE_FAN, 0, 4); 
					}
				
					texCoords[0].u = 0; 
					texCoords[0].v = 1; 
					texCoords[1].u = 0; 
					texCoords[1].v = 0.5;
					texCoords[2].u = 1;
					texCoords[2].v = 0.5;
					texCoords[3].u = 1;
					texCoords[3].v = 1;
					glEnableClientState(GL_TEXTURE_COORD_ARRAY);
					//glVertexPointer(2, GL_FLOAT, 0, mVertices);
					glVertexPointer(2, GL_FLOAT, 0, mVerticesCopy);
					glTexCoordPointer(2, GL_FLOAT, 0, texCoords);
					Region::const_iterator itCopy1 = clip.begin();	  
					Region::const_iterator const endCopy1 = clip.end();   
					while (itCopy1!= endCopy1) {   
						const Rect& rCopy1 = *itCopy1++;	
						const GLint syCopy1 = fbHeight - (rCopy1.top + rCopy1.height());  
						glScissor(rCopy1.left, syCopy1/2 + (fbHeight/2), rCopy1.width(), rCopy1.height()/2); 
						glDrawArrays(GL_TRIANGLE_FAN, 0, 4);			
					}		
							
				}
				else{
						//draw 2D surface to buttom 	
						 
					texCoords[0].u = 0;
					texCoords[0].v = 1;
					texCoords[1].u = 0;
					texCoords[1].v = 0;
					texCoords[2].u = 1;
					texCoords[2].v = 0;
					texCoords[3].u = 1;
					texCoords[3].v = 1; 	
					glEnableClientState(GL_TEXTURE_COORD_ARRAY);
					glVertexPointer(2, GL_FLOAT, 0, mVerticesCopy1);
					glTexCoordPointer(2, GL_FLOAT, 0, texCoords);		
					Region::const_iterator it = clip.begin();
					Region::const_iterator const end = clip.end();
					while (it != end) {
						const Rect& r = *it++;		
						const GLint sy = fbHeight - (r.top + r.height());
						glScissor(r.left, sy/2, r.width(), r.height()/2);
									
						glDrawArrays(GL_TRIANGLE_FAN, 0, 4); 
					}
						//draw 2D surface to top				
					glVertexPointer(2, GL_FLOAT, 0, mVerticesCopy); 	
					glTexCoordPointer(2, GL_FLOAT, 0, texCoords);		
					Region::const_iterator itCopy = clip.begin();	 
					Region::const_iterator const endCopy = clip.end();	 
					while (itCopy!= endCopy) {	 
						const Rect& rCopy = *itCopy++;	  
						const GLint syCopy = fbHeight - (rCopy.top + rCopy.height());
						glScissor(rCopy.left, syCopy/2 + (fbHeight/2), rCopy.width(), rCopy.height()/2);
						glDrawArrays(GL_TRIANGLE_FAN, 0, 4);			
					}
				}

}
Esempio n. 23
0
void LayerBase::drawSideBySide(const Region& clip ,uint32_t hw_w_half ,uint32_t fbHeight ,uint8_t eType ) const
{
	struct TexCoords {
							GLfloat u;
							GLfloat v;
							};			 
	TexCoords texCoords[4];

	GLfloat mVerticesCopy1[4][2];
	GLfloat mVerticesCopy[4][2]; 
	mVerticesCopy1[0][0] = mVertices[0][0]; 
	mVerticesCopy1[0][1] = mVertices[0][1]; 
	mVerticesCopy1[1][0] = mVertices[1][0]; 
	mVerticesCopy1[1][1] = mVertices[1][1]; 
	mVerticesCopy1[2][0] = mVertices[2][0]; 
	mVerticesCopy1[2][1] = mVertices[2][1]; 
	mVerticesCopy1[3][0] = mVertices[3][0]; 
	mVerticesCopy1[3][1] = mVertices[3][1]; 	
	for (size_t i=0 ; i<4 ; i++){
		mVerticesCopy1[i][0] /= 2;						
	}
	mVerticesCopy[0][0] = mVerticesCopy1[0][0] + hw_w_half; 
	mVerticesCopy[0][1] = mVerticesCopy1[0][1]; 
	mVerticesCopy[1][0] = mVerticesCopy1[1][0] + hw_w_half; 
	mVerticesCopy[1][1] = mVerticesCopy1[1][1]; 
	mVerticesCopy[2][0] = mVerticesCopy1[2][0] + hw_w_half; 
	mVerticesCopy[2][1] = mVerticesCopy1[2][1]; 
	mVerticesCopy[3][0] = mVerticesCopy1[3][0] + hw_w_half; 
	mVerticesCopy[3][1] = mVerticesCopy1[3][1];
					//3d surface
	LOGD("-------550-----Draw--in 3d surface --- mDrawingState.flags = %d", int(mDrawingState.flags));
	if((ISurfaceComposer::eLayerSideBySide == eType))
	{
					//draw 3D full to whole FB
						
		texCoords[0].u = 0; 
		texCoords[0].v = 1; 
		texCoords[1].u = 0; 
		texCoords[1].v = 0;
		texCoords[2].u = 0.5;
		texCoords[2].v = 0;
		texCoords[3].u = 0.5;
		texCoords[3].v = 1;
		glEnableClientState(GL_TEXTURE_COORD_ARRAY);			
		glVertexPointer(2, GL_FLOAT, 0, mVerticesCopy1);
		glTexCoordPointer(2, GL_FLOAT, 0, texCoords);
		Region::const_iterator it = clip.begin();
		Region::const_iterator const end = clip.end();			
		while (it != end) {
			const Rect& r = *it++;		
			const GLint sy = fbHeight - (r.top + r.height());			
			glScissor(r.left/2, sy, r.width()/2, r.height());			
			glDrawArrays(GL_TRIANGLE_FAN, 0, 4); 
		}
			
		texCoords[0].u = 0.5;	
		texCoords[0].v = 1; 
		texCoords[1].u = 0.5;	
		texCoords[1].v = 0;
		texCoords[2].u = 1;
		texCoords[2].v = 0;
		texCoords[3].u = 1;
		texCoords[3].v = 1;
		glEnableClientState(GL_TEXTURE_COORD_ARRAY);
				//glVertexPointer(2, GL_FLOAT, 0, mVertices);
		glVertexPointer(2, GL_FLOAT, 0, mVerticesCopy);
		glTexCoordPointer(2, GL_FLOAT, 0, texCoords);
		Region::const_iterator itCopy1 = clip.begin();	  
		Region::const_iterator const endCopy1 = clip.end();   
		while (itCopy1!= endCopy1) {   
			const Rect& rCopy1 = *itCopy1++;	
			const GLint syCopy1 = fbHeight - (rCopy1.top + rCopy1.height());  
			glScissor(rCopy1.left/2+hw_w_half, syCopy1, rCopy1.width()/2, rCopy1.height()); 
			glDrawArrays(GL_TRIANGLE_FAN, 0, 4);			
		}		
						
	}
	else{
					//draw 2D surface to left		
					 
				texCoords[0].u = 0;
				texCoords[0].v = 1;
				texCoords[1].u = 0;
				texCoords[1].v = 0;
				texCoords[2].u = 1;
				texCoords[2].v = 0;
				texCoords[3].u = 1;
				texCoords[3].v = 1; 	
				glEnableClientState(GL_TEXTURE_COORD_ARRAY);
				glVertexPointer(2, GL_FLOAT, 0, mVerticesCopy1);
				glTexCoordPointer(2, GL_FLOAT, 0, texCoords);		
				Region::const_iterator it = clip.begin();
				Region::const_iterator const end = clip.end();
				while (it != end) {
					const Rect& r = *it++;		
					const GLint sy = fbHeight - (r.top + r.height());			
					glScissor(r.left/2, sy, r.width()/2, r.height());			
					glDrawArrays(GL_TRIANGLE_FAN, 0, 4); 
				}
					//draw 2D surface to right				
				glVertexPointer(2, GL_FLOAT, 0, mVerticesCopy); 	
				glTexCoordPointer(2, GL_FLOAT, 0, texCoords);		
				Region::const_iterator itCopy = clip.begin();	 
				Region::const_iterator const endCopy = clip.end();	 
				while (itCopy!= endCopy) {	 
					const Rect& rCopy = *itCopy++;	  
					const GLint syCopy = fbHeight - (rCopy.top + rCopy.height());  
					glScissor(rCopy.left/2+hw_w_half, syCopy, rCopy.width()/2, rCopy.height()); 
					glDrawArrays(GL_TRIANGLE_FAN, 0, 4);			
				}
			}
}
void LayerBlur::onDraw(const Region& clip) const
{
    const DisplayHardware& hw(graphicPlane(0).displayHardware());
    const uint32_t fbHeight = hw.getHeight();
    int x = mTransformedBounds.left;
    int y = mTransformedBounds.top;
    int w = mTransformedBounds.width();
    int h = mTransformedBounds.height();
    GLint X = x;
    GLint Y = fbHeight - (y + h);
    if (X < 0) {
        w += X;
        X = 0;
    }
    if (Y < 0) {
        h += Y;
        Y = 0;
    }
    if (w<0 || h<0) {
        // we're outside of the framebuffer
        return;
    }

    if (mTextureName == -1U) {
        // create the texture name the first time
        // can't do that in the ctor, because it runs in another thread.
        glGenTextures(1, &mTextureName);
        glGetIntegerv(GL_IMPLEMENTATION_COLOR_READ_FORMAT_OES, &mReadFormat);
        glGetIntegerv(GL_IMPLEMENTATION_COLOR_READ_TYPE_OES, &mReadType);
        if (mReadFormat != GL_RGB || mReadType != GL_UNSIGNED_SHORT_5_6_5) {
            mReadFormat = GL_RGBA;
            mReadType = GL_UNSIGNED_BYTE;
            mBlurFormat = GGL_PIXEL_FORMAT_RGBX_8888;
        }
    }

    Region::const_iterator it = clip.begin();
    Region::const_iterator const end = clip.end();
    if (it != end) {
#if defined(GL_OES_EGL_image_external)
        if (GLExtensions::getInstance().haveTextureExternal()) {
            glDisable(GL_TEXTURE_EXTERNAL_OES);
        }
#endif
        glEnable(GL_TEXTURE_2D);
        glBindTexture(GL_TEXTURE_2D, mTextureName);

        if (mRefreshCache) {
            mRefreshCache = false;
            mAutoRefreshPending = false;

            int32_t pixelSize = 4;
            int32_t s = w;
            if (mReadType == GL_UNSIGNED_SHORT_5_6_5) {
                // allocate enough memory for 4-bytes (2 pixels) aligned data
                s = (w + 1) & ~1;
                pixelSize = 2;
            }

            uint16_t* const pixels = (uint16_t*)malloc(s*h*pixelSize);

            // This reads the frame-buffer, so a h/w GL would have to
            // finish() its rendering first. we don't want to do that
            // too often. Read data is 4-bytes aligned.
            glReadPixels(X, Y, w, h, mReadFormat, mReadType, pixels);

            // blur that texture.
            GGLSurface bl;
            bl.version = sizeof(GGLSurface);
            bl.width = w;
            bl.height = h;
            bl.stride = s;
            bl.format = mBlurFormat;
            bl.data = (GGLubyte*)pixels;            
            blurFilter(&bl, 8, 2);

            if (GLExtensions::getInstance().haveNpot()) {
                glTexImage2D(GL_TEXTURE_2D, 0, mReadFormat, w, h, 0,
                        mReadFormat, mReadType, pixels);
                mWidthScale  = 1.0f / w;
                mHeightScale =-1.0f / h;
                mYOffset = 0;
            } else {
                GLuint tw = 1 << (31 - clz(w));
                GLuint th = 1 << (31 - clz(h));
                if (tw < GLuint(w)) tw <<= 1;
                if (th < GLuint(h)) th <<= 1;
                glTexImage2D(GL_TEXTURE_2D, 0, mReadFormat, tw, th, 0,
                        mReadFormat, mReadType, NULL);
                glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, w, h, 
                        mReadFormat, mReadType, pixels);
                mWidthScale  = 1.0f / tw;
                mHeightScale =-1.0f / th;
                mYOffset = th-h;
            }

            free((void*)pixels);
        }

        const State& s = drawingState();
        if (UNLIKELY(s.alpha < 0xFF)) {
            const GLfloat alpha = s.alpha * (1.0f/255.0f);
            glColor4f(0, 0, 0, alpha);
            glEnable(GL_BLEND);
            glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
            glTexEnvx(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
        } else {
            glDisable(GL_BLEND);
        }

        if (mFlags & DisplayHardware::SLOW_CONFIG) {
            glDisable(GL_DITHER);
        } else {
            glEnable(GL_DITHER);
        }

        glTexEnvx(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
        glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
        glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);

#ifdef AVOID_DRAW_TEXTURE
        if(UNLIKELY(transformed()))
#endif
        {
            glMatrixMode(GL_TEXTURE);
            glLoadIdentity();
            glScalef(mWidthScale, mHeightScale, 1);
            glTranslatef(-x, mYOffset - y, 0);
            glEnableClientState(GL_TEXTURE_COORD_ARRAY);
            glVertexPointer(2, GL_FLOAT, 0, mVertices);
            glTexCoordPointer(2, GL_FLOAT, 0, mVertices);
            while (it != end) {
                const Rect& r = *it++;
                const GLint sy = fbHeight - (r.top + r.height());
                glScissor(r.left, sy, r.width(), r.height());
                glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
            }
            glDisableClientState(GL_TEXTURE_COORD_ARRAY);
        }
#ifdef AVOID_DRAW_TEXTURE
        else{
            Rect r;
            GLint crop[4] = { 0, 0, w, h };
            glTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_CROP_RECT_OES, crop);
            y = fbHeight - (y + h);
            while (it != end) {
                const Rect& r = *it++;
                const GLint sy = fbHeight - (r.top + r.height());
                glScissor(r.left, sy, r.width(), r.height());
                glDrawTexiOES(x, y, 0, w, h);
            }
        }
#endif
        glLoadIdentity();
        glMatrixMode(GL_MODELVIEW);
    }
}
Esempio n. 25
0
void LayerBase::drawWithOpenGL(const Region& clip) const
{
    const DisplayHardware& hw(graphicPlane(0).displayHardware());
    const uint32_t fbHeight = hw.getHeight();
    const State& s(drawingState());

    GLenum src = mPremultipliedAlpha ? GL_ONE : GL_SRC_ALPHA;
    if (UNLIKELY(s.alpha < 0xFF)) {
        const GLfloat alpha = s.alpha * (1.0f/255.0f);
        if (mPremultipliedAlpha) {
            glColor4f(alpha, alpha, alpha, alpha);
        } else {
            glColor4f(1, 1, 1, alpha);
        }
        glEnable(GL_BLEND);
        glBlendFunc(src, GL_ONE_MINUS_SRC_ALPHA);
        glTexEnvx(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
    } else {
        glColor4f(1, 1, 1, 1);
        glTexEnvx(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
        if (!isOpaque()) {
            glEnable(GL_BLEND);
            glBlendFunc(src, GL_ONE_MINUS_SRC_ALPHA);
        } else {
            glDisable(GL_BLEND);
        }
    }

    struct TexCoords {
        GLfloat u;
        GLfloat v;
    };

    TexCoords texCoords[4];
    texCoords[0].u = 0;
    texCoords[0].v = 1;
    texCoords[1].u = 0;
    texCoords[1].v = 0;
    texCoords[2].u = 1;
    texCoords[2].v = 0;
    texCoords[3].u = 1;
    texCoords[3].v = 1;

    if (drawRotatedTexture) {
        int tWidth = mTransformedBounds.right - mTransformedBounds.left;
        int val = drawRotatedTexture(mOrientation, tWidth, fbHeight,
                                             clip, (GLfloat *) mVertices,
                                                  (GLfloat *) texCoords);
        if (val == NO_ERROR) {
            return;
        }
    }

    glEnableClientState(GL_TEXTURE_COORD_ARRAY);
    glVertexPointer(2, GL_FLOAT, 0, mVertices);
    glTexCoordPointer(2, GL_FLOAT, 0, texCoords);

    Region::const_iterator it = clip.begin();
    Region::const_iterator const end = clip.end();
    while (it != end) {
        const Rect& r = *it++;
        const GLint sy = fbHeight - (r.top + r.height());
        glScissor(r.left, sy, r.width(), r.height());
        glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
    }
    glDisableClientState(GL_TEXTURE_COORD_ARRAY);
    glDisable(GL_BLEND);
}
bool Region::isTriviallyEqual(const Region& region) const {
    return begin() == region.begin();
}
void LayerBase::drawWithOpenGL(const Region& clip, const Texture& texture) const
{
    const DisplayHardware& hw(graphicPlane(0).displayHardware());
    const uint32_t fbHeight = hw.getHeight();
    const State& s(drawingState());
    
    // bind our texture
    TextureManager::activateTexture(texture, needsFiltering());
    uint32_t width  = texture.width; 
    uint32_t height = texture.height;

    GLenum src = mPremultipliedAlpha ? GL_ONE : GL_SRC_ALPHA;

    int renderEffect = mFlinger->getRenderEffect();
    int renderColorR = mFlinger->getRenderColorR();
    int renderColorG = mFlinger->getRenderColorG();
    int renderColorB = mFlinger->getRenderColorB();

    bool noEffect = renderEffect == 0;

    if (UNLIKELY(s.alpha < 0xFF) && noEffect) {
        const GLfloat alpha = s.alpha * (1.0f/255.0f);
        if (mPremultipliedAlpha) {
            glColor4f(alpha, alpha, alpha, alpha);
        } else {
            glColor4f(1, 1, 1, alpha);
        }
        glEnable(GL_BLEND);
        glBlendFunc(src, GL_ONE_MINUS_SRC_ALPHA);
        glTexEnvx(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
    } else if (noEffect) {
        glColor4f(1, 1, 1, 1);
        glTexEnvx(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
        if (needsBlending()) {
            glEnable(GL_BLEND);
            glBlendFunc(src, GL_ONE_MINUS_SRC_ALPHA);
        } else {
            glDisable(GL_BLEND);
        }
    } else {
        // Apply a render effect, which is simple color masks for now.
        GLenum env, src;
        env = GL_MODULATE;
        src = mPremultipliedAlpha ? GL_ONE : GL_SRC_ALPHA;
        const GGLfixed alpha = (s.alpha << 16)/255;
        switch (renderEffect) {
            case RENDER_EFFECT_NIGHT:
                glColor4x(alpha, alpha*0.6204, alpha*0.3018, alpha);
                break;
            case RENDER_EFFECT_TERMINAL:
                glColor4x(0, alpha, 0, alpha);
                break;
            case RENDER_EFFECT_BLUE:
                glColor4x(0, 0, alpha, alpha);
                break;
            case RENDER_EFFECT_AMBER:
                glColor4x(alpha, alpha*0.75, 0, alpha);
                break;
            case RENDER_EFFECT_SALMON:
                glColor4x(alpha, alpha*0.5, alpha*0.5, alpha);
                break;
            case RENDER_EFFECT_FUSCIA:
                glColor4x(alpha, 0, alpha*0.5, alpha);
                break;
            case RENDER_EFFECT_N1_CALIBRATED_N:
                glColor4x(alpha*renderColorR/1000, alpha*renderColorG/1000, alpha*renderColorB/1000, alpha);
                break;
            case RENDER_EFFECT_N1_CALIBRATED_R:
                glColor4x(alpha*(renderColorR-50)/1000, alpha*renderColorG/1000, alpha*(renderColorB-30)/1000, alpha);
                break;
            case RENDER_EFFECT_N1_CALIBRATED_C:
                glColor4x(alpha*renderColorR/1000, alpha*renderColorG/1000, alpha*(renderColorB+30)/1000, alpha);
                break;
            case RENDER_EFFECT_RED:
                glColor4x(alpha, 0, 0, alpha);
                break;
        }
        glEnable(GL_BLEND);
        glBlendFunc(src, GL_ONE_MINUS_SRC_ALPHA);
        glTexEnvx(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, env);
    }

    /*
     *  compute texture coordinates
     *  here, we handle NPOT, cropping and buffer transformations
     */

    GLfloat cl, ct, cr, cb;
    if (!mBufferCrop.isEmpty()) {
        // source is cropped
        const GLfloat us = (texture.NPOTAdjust ? texture.wScale : 1.0f) / width;
        const GLfloat vs = (texture.NPOTAdjust ? texture.hScale : 1.0f) / height;
        cl = mBufferCrop.left   * us;
        ct = mBufferCrop.top    * vs;
        cr = mBufferCrop.right  * us;
        cb = mBufferCrop.bottom * vs;
    } else {
        cl = 0;
        ct = 0;
        cr = (texture.NPOTAdjust ? texture.wScale : 1.0f);
        cb = (texture.NPOTAdjust ? texture.hScale : 1.0f);
    }

    /*
     * For the buffer transformation, we apply the rotation last.
     * Since we're transforming the texture-coordinates, we need
     * to apply the inverse of the buffer transformation:
     *   inverse( FLIP_V -> FLIP_H -> ROT_90 )
     *   <=> inverse( ROT_90 * FLIP_H * FLIP_V )
     *    =  inverse(FLIP_V) * inverse(FLIP_H) * inverse(ROT_90)
     *    =  FLIP_V * FLIP_H * ROT_270
     *   <=> ROT_270 -> FLIP_H -> FLIP_V
     *
     * The rotation is performed first, in the texture coordinate space.
     *
     */

    struct TexCoords {
        GLfloat u;
        GLfloat v;
    };

    enum {
        // name of the corners in the texture map
        LB = 0, // left-bottom
        LT = 1, // left-top
        RT = 2, // right-top
        RB = 3  // right-bottom
    };

    // vertices in screen space
    int vLT = LB;
    int vLB = LT;
    int vRB = RT;
    int vRT = RB;

    // the texture's source is rotated
    uint32_t transform = mBufferTransform;
    if (transform & HAL_TRANSFORM_ROT_90) {
        vLT = RB;
        vLB = LB;
        vRB = LT;
        vRT = RT;
    }
    if (transform & HAL_TRANSFORM_FLIP_V) {
        swap(vLT, vLB);
        swap(vRT, vRB);
    }
    if (transform & HAL_TRANSFORM_FLIP_H) {
        swap(vLT, vRT);
        swap(vLB, vRB);
    }

    TexCoords texCoords[4];
    texCoords[vLT].u = cl;
    texCoords[vLT].v = ct;
    texCoords[vLB].u = cl;
    texCoords[vLB].v = cb;
    texCoords[vRB].u = cr;
    texCoords[vRB].v = cb;
    texCoords[vRT].u = cr;
    texCoords[vRT].v = ct;

    if (needsDithering()) {
        glEnable(GL_DITHER);
    } else {
        glDisable(GL_DITHER);
    }

    glEnableClientState(GL_TEXTURE_COORD_ARRAY);
    glVertexPointer(2, GL_FLOAT, 0, mVertices);
    glTexCoordPointer(2, GL_FLOAT, 0, texCoords);

    Region::const_iterator it = clip.begin();
    Region::const_iterator const end = clip.end();
    while (it != end) {
        const Rect& r = *it++;
        const GLint sy = fbHeight - (r.top + r.height());
        glScissor(r.left, sy, r.width(), r.height());
        glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
    }
    glDisableClientState(GL_TEXTURE_COORD_ARRAY);
}
bool Region::validate(const Region& reg, const char* name, bool silent)
{
    bool result = true;
    const_iterator cur = reg.begin();
    const_iterator const tail = reg.end();
    const_iterator prev = cur;
    Rect b(*prev);
    while (cur != tail) {
        if (cur->isValid() == false) {
            ALOGE_IF(!silent, "%s: region contains an invalid Rect", name);
            result = false;
        }
        if (cur->right > region_operator<Rect>::max_value) {
            ALOGE_IF(!silent, "%s: rect->right > max_value", name);
            result = false;
        }
        if (cur->bottom > region_operator<Rect>::max_value) {
            ALOGE_IF(!silent, "%s: rect->right > max_value", name);
            result = false;
        }
        if (prev != cur) {
            b.left   = b.left   < cur->left   ? b.left   : cur->left;
            b.top    = b.top    < cur->top    ? b.top    : cur->top;
            b.right  = b.right  > cur->right  ? b.right  : cur->right;
            b.bottom = b.bottom > cur->bottom ? b.bottom : cur->bottom;
            if ((*prev < *cur) == false) {
                ALOGE_IF(!silent, "%s: region's Rects not sorted", name);
                result = false;
            }
            if (cur->top == prev->top) {
                if (cur->bottom != prev->bottom) {
                    ALOGE_IF(!silent, "%s: invalid span %p", name, cur);
                    result = false;
                } else if (cur->left < prev->right) {
                    ALOGE_IF(!silent,
                            "%s: spans overlap horizontally prev=%p, cur=%p",
                            name, prev, cur);
                    result = false;
                }
            } else if (cur->top < prev->bottom) {
                ALOGE_IF(!silent,
                        "%s: spans overlap vertically prev=%p, cur=%p",
                        name, prev, cur);
                result = false;
            }
            prev = cur;
        }
        cur++;
    }
    if (b != reg.getBounds()) {
        result = false;
        ALOGE_IF(!silent,
                "%s: invalid bounds [%d,%d,%d,%d] vs. [%d,%d,%d,%d]", name,
                b.left, b.top, b.right, b.bottom,
                reg.getBounds().left, reg.getBounds().top, 
                reg.getBounds().right, reg.getBounds().bottom);
    }
    if (reg.mStorage.size() == 2) {
        result = false;
        ALOGE_IF(!silent, "%s: mStorage size is 2, which is never valid", name);
    }
    if (result == false && !silent) {
        reg.dump(name);
        CallStack stack(LOG_TAG);
    }
    return result;
}